首先祝各位节日快乐
斯波题,若四条边界上有1,直接输出2,否则输出4。好玩的是我还成功误导了某位同学,使他误以为是DFS(笑)。
#include<bits/stdc++.h>
#define N 101
using namespace std;
int n,m;
int main(){
freopen("table.in","r",stdin);
freopen("table.out","w",stdout);
cin>>n>>m;
int flag=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
cin>>x;
if (x)
if (i==1||i==n||j==1||j==m) flag=1;
}
}
if (flag) cout<<2; else cout<<4;
return 0;
}
考场上愣是没看出来DP,惨遭20。其实正解也不难,见下。
将连续的相同字符压缩为同一个,
例如aabbaacc即为abac
我们可以发现,字母的顺序是不会换的,比如abac就不可能变换为abca。
所以就可以用类似背包的思想,f[i][x][y][z]代表最后一个选的字符是原串第i位,用了x个a y个b z个c的答案。
方程就是
f[nex[i][0]][a+1][b][c]=(f[nex[i][0]][a+1][b][c]+f[i][a][b][c]);
f[nex[i][1]][a][b+1][c]=(f[nex[i][1]][a][b+1][c]+f[i][a][b][c]);
f[nex[i][2]][a][b][c+1]=(f[nex[i][2]][a][b][c+1]+f[i][a][b][c]);
其中next[i][0..2]为预处理原串字符i后面(包括自身)最近的’a”b”c’的位置。
代码如下
#include<bits/stdc++.h>
#define ll long long
#define mod 51123987
using namespace std;
int n,nex[210][3],stand;
ll f[155][55][55][55],ans;
char c[155];
bool check(int a,int b,int c){
return (a+b+c==n)&&(fabs(a-b)<=1)&&(fabs(c-b)<=1)&&(fabs(a-c)<=1);
}
int main(){
freopen("balance.in", "r", stdin);
freopen("balance.out", "w", stdout);
cin>>n;
cin>>c;
nex[n+1][0]=nex[n+1][1]=nex[n+1][2]=n+1;
for(int i=n;i>=1;i--){
nex[i][0]=nex[i+1][0],nex[i][1]=nex[i+1][1],nex[i][2]=nex[i+1][2];
nex[i][c[i-1]-'a']=i;
}
ans=0,stand=(n+2)/3,f[1][0][0][0]=1;
for(int i=1;i<=n;i++)
for(int a=0;a<=stand;a++)
for(int b=0;b<=stand;b++)
for(int c=0;c<=stand;c++){
if(check(a,b,c)){
ans+=f[i][a][b][c];
}
if(nex[i][0]<=n) f[nex[i][0]][a+1][b][c]=(f[nex[i][0]][a+1][b][c]+f[i][a][b][c])%mod;
if(nex[i][1]<=n) f[nex[i][1]][a][b+1][c]=(f[nex[i][1]][a][b+1][c]+f[i][a][b][c])%mod;
if(nex[i][2]<=n) f[nex[i][2]][a][b][c+1]=(f[nex[i][2]][a][b][c+1]+f[i][a][b][c])%mod;
}
cout<<ans%mod<<endl;
return 0;
}
如果熟悉二分图和各种树上操作的话应该不难(但是我不会)。
思路很明确:给一张无向图,求删掉哪几条边可以变成二分图;
定义一个环为奇环当且仅当环包含的边数为奇数,偶环同理。
我们会发现,
如果没有奇环,那么任何边都可以删;
如果只有一个奇环,那么奇环上的边都可以被删;
如果多于1个,必须选在所有奇环且不在偶环上的点;
那么怎么找奇环呢?
这里要说到DFS树的两个特点,第一,树上的边要么构成一条链,要么是返祖边。第二,树上的LCA就是深度较浅的点。
这里的返祖边就是我们要找的环了。考虑到树上差分,它应该在两个端点+1,LCA-2。根据上面的第二点,我们将深度较浅的点+1-2即可。
统计tag==n的点,输出他的father即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define ri register int
#define il inline
#define fi first
#define se second
#define mp make_pair
#define pi pair<int,int>
#define mem0(x) memset((x),0,sizeof (x))
#define mem1(x) memset((x),0x3f,sizeof (x))
#define gc getchar
#define pb push_back
template<class T>void in(T &x){
x = 0; bool f = 0; char c = gc();
while (c < '0' || c > '9') {if (c == '-') f = 1; c = gc();}
while ('0' <= c && c <= '9') {x = (x << 3) + (x << 1) + (c ^ 48); c = gc();}
if (f) x = -x;
}
#undef gc
void out(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
#define N 10010
#define M N<<2
int n, m;
int v[M], u[M], nx[M], k[M];
int cnt = 1, head[N];
il void add(int uu, int vv) {
u[++cnt] = uu, v[cnt] = vv, nx[cnt] = head[uu];
head[uu] = cnt;
k[cnt] = (cnt >> 1);
}
int dep[N];
bool vis[N];
int tag[N];
int zt;
vector<int>ans;
int lst;
void dfs(int x, int f, int d) {
//printf("V %d\n",x);
dep[x] = d;
vis[x] = 1;
for (ri i = head[x]; i; i = nx[i]) {
if (i == f) continue;
if (!vis[v[i]]) {
dfs(v[i], i ^ 1, d + 1);
}
else {
if (dep[v[i]] < dep[x]) continue;
if ((dep[v[i]] - dep[x] + 1) & 1) {
tag[x]--; // in fact +1 -2
tag[v[i]]++;
zt++;
lst=k[i];
}
else {
tag[x]++;
tag[v[i]]--;
}
}
}
}
int dfs2(int x, int f) {
vis[x] = 1;
int res = tag[x];
for (ri i = head[x]; i; i = nx[i]) {
if (vis[v[i]]) continue;
res += dfs2(v[i], i);
}
if (res == zt) ans.pb(k[f]);
//printf("T %d %d %d\n",x,res,tag[x]);
return res;
}
signed main() {
in(n), in(m);
for (ri i = 1, a, b; i <= m; ++i) {
in(a), in(b);
add(a, b);
add(b, a);
}
for (ri i = 1; i <= n; ++i) {
if (!vis[i]) dfs(i, 0, 0);
}
if (zt == 0) {
//cout << "A";
printf("%d\n", m);
for (ri i = 1; i <= m; ++i) printf("%d ", i);
return 0;
}
if(zt==1) ans.pb(lst);
//cout<<zt;
mem0(vis);
for (ri i = 1; i <= n; ++i) {
if (!vis[i]) dfs2(i, 0);
}
sort(ans.begin(), ans.end());
printf("%d\n", ans.size());
for (ri i = 0; i < ans.size(); ++i) {
printf("%d ", ans[i]);
}
return 0;
}