bzoj1412
比较裸的流了。。显然是最小割,S连狼=inf,羊连T=inf,狼羊和空地间=1,然后跑就行了,dinic略慢。。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<ctime> 5 #include<cmath> 6 #include<iostream> 7 #include<algorithm> 8 #include<queue> 9 #include<stack> 10 #include<set> 11 #define clr(a,x) memset(a,x,sizeof(a)) 12 #define rep(i,l,r) for(int i=(l);i<(r);i++) 13 using namespace std; 14 typedef long long ll; 15 typedef pair<int,int> pii; 16 #define mkp(a,b) make_pair(a,b) 17 int read(){ 18 int ans=0,f=1; 19 char c=getchar(); 20 while(!isdigit(c)){ 21 if(c=='-') f=-1; 22 c=getchar(); 23 } 24 while(isdigit(c)){ 25 ans=ans*10+c-'0'; 26 c=getchar(); 27 } 28 return ans*f; 29 } 30 const int maxn=109,inf=0x3fffffff; 31 int S,T,n,m,a[maxn][maxn],d[maxn*maxn]; 32 #define cnt(a,b) (((a)-1)*m+(b)) 33 struct edge{ 34 int v,w; 35 edge*next,*r; 36 }e[maxn*maxn<<3],*fir[maxn*maxn],*cur[maxn*maxn],*pt=e; 37 void add(int u,int v,int w){ 38 pt->v=v;pt->w=w; 39 pt->next=fir[u]; 40 fir[u]=pt++; 41 } 42 void addedge(int u,int v,int w){ 43 add(u,v,w);add(v,u,0); 44 fir[u]->r=fir[v];fir[v]->r=fir[u]; 45 } 46 bool bfs(){ 47 queue<int>Q;Q.push(S); 48 clr(d,0);d[S]=1; 49 while(!Q.empty()){ 50 int x=Q.front();Q.pop(); 51 for(edge*e=fir[x];e;e=e->next){ 52 if(e->w&&!d[e->v]){ 53 d[e->v]=d[x]+1;Q.push(e->v); 54 } 55 } 56 } 57 return d[T]; 58 } 59 int dfs(int x,int w){ 60 if(x==T||!w) return w; 61 int f=0; 62 for(edge*&e=cur[x];e;e=e->next){ 63 if(e->w&&d[e->v]==d[x]+1){ 64 int g=dfs(e->v,min(e->w,w)); 65 if(g>0){ 66 f+=g; 67 e->w-=g; 68 e->r->w+=g; 69 if(!(w-=g)) break; 70 } 71 } 72 } 73 return f; 74 } 75 int maxflow(){ 76 int ans=0; 77 while(bfs()){ 78 rep(i,S,T+1) cur[i]=fir[i]; 79 ans+=dfs(S,inf); 80 } 81 return ans; 82 } 83 int main(){ 84 n=read();m=read();S=0;T=n*m+1; 85 rep(i,1,n+1) 86 rep(j,1,m+1) a[i][j]=read(); 87 rep(i,1,n+1) 88 rep(j,1,m+1){ 89 if(a[i][j]==1) addedge(S,cnt(i,j),inf); 90 if(a[i][j]==2) addedge(cnt(i,j),T,inf); 91 if(i-1>0&&(a[i-1][j]!=a[i][j]||!(a[i-1][j]|a[i][j]))) addedge(cnt(i-1,j),cnt(i,j),1); 92 if(i+1<=n&&(a[i+1][j]!=a[i][j]||!(a[i+1][j]|a[i][j]))) addedge(cnt(i+1,j),cnt(i,j),1); 93 if(j-1>0&&(a[i][j-1]!=a[i][j]||!(a[i][j-1]|a[i][j]))) addedge(cnt(i,j-1),cnt(i,j),1); 94 if(j+1<=m&&(a[i][j+1]!=a[i][j]||!(a[i][j+1]|a[i][j]))) addedge(cnt(i,j+1),cnt(i,j),1); 95 } 96 printf("%d\n",maxflow()); 97 return 0; 98 }
1412: [ZJOI2009]狼和羊的故事
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1944 Solved: 1014
[Submit][Status][Discuss]
Description
“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
Input
文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。
Output
文件中仅包含一个整数ans,代表篱笆的最短长度。
Sample Input
2 2
2 2
1 1
2 2
1 1
Sample Output
2
数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
HINT
Source