BZOJ1693: [Usaco2007 Demo]Asteroids
n<=500 *n的格子,给m<=10000个格子有人,一炮可以清掉一行或一列的人(莫名的爽!)求最少几炮干掉所有人。
经典二分图模型!行成点,列成点,一个点就连接一行一列,表示这一行或这一列必选其一!
不喜欢匈牙利!跑网络流!
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 #include<iostream> 6 using namespace std; 7 8 int n,m; 9 #define maxn 1011 10 #define maxm 22011 11 struct Edge{int to,next,cap,flow;}; 12 const int inf=0x3f3f3f3f; 13 struct Network 14 { 15 Edge edge[maxm];int first[maxn],le,n,s,t; 16 void clear(int n) 17 { 18 memset(first,0,sizeof(first)); 19 le=2;this->n=n; 20 } 21 void in(int x,int y,int cap) 22 { 23 Edge &e=edge[le]; 24 e.to=y;e.cap=cap;e.flow=0; 25 e.next=first[x];first[x]=le++; 26 } 27 void insert(int x,int y,int cap) {in(x,y,cap);in(y,x,0);} 28 int dis[maxn],cur[maxn],que[maxn],head,tail; 29 bool bfs() 30 { 31 memset(dis,0,sizeof(dis)); 32 dis[s]=1; 33 que[head=(tail=1)-1]=s; 34 while (head!=tail) 35 { 36 const int now=que[head++]; 37 for (int i=first[now];i;i=edge[i].next) 38 { 39 Edge &e=edge[i]; 40 if (e.cap>e.flow && !dis[e.to]) 41 { 42 dis[e.to]=dis[now]+1; 43 que[tail++]=e.to; 44 } 45 } 46 } 47 return dis[t]; 48 } 49 int dfs(int x,int a) 50 { 51 if (x==t || !a) return a; 52 int flow=0,f; 53 for (int &i=cur[x];i;i=edge[i].next) 54 { 55 Edge &e=edge[i]; 56 if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0) 57 { 58 e.flow+=f; 59 edge[i^1].flow-=f; 60 a-=f; 61 flow+=f; 62 if (!a) break; 63 } 64 } 65 return flow; 66 } 67 int Dinic(int s,int t) 68 { 69 this->s=s,this->t=t; 70 int ans=0; 71 while (bfs()) 72 { 73 for (int i=1;i<=n;i++) cur[i]=first[i]; 74 ans+=dfs(s,inf); 75 } 76 return ans; 77 } 78 }g; 79 int x,y; 80 int main() 81 { 82 scanf("%d%d",&n,&m); 83 g.clear(n*2+2); 84 int s=g.n-1,t=g.n; 85 for (int i=1;i<=n;i++) g.insert(s,i,1); 86 for (int i=n+1;i<=n*2;i++) g.insert(i,t,1); 87 for (int i=1;i<=m;i++) 88 { 89 scanf("%d%d",&x,&y); 90 g.insert(x,y+n,1); 91 } 92 printf("%d\n",g.Dinic(s,t)); 93 return 0; 94 }