BZOJ1741: [Usaco2005 nov]Asteroids 穿越小行星群

n<=500,n*n网格给m<=10000个点,每次发射子弹打掉一行或一列的点,求最少几发子弹。

网络流经典模型,每行每列看成点,一个(x,y)表示,表示第x行的点和表示第y列的点必有一个要选,连边。接下来二分图匹配或最大流即可。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 //#include<iostream>
  6 using namespace std;
  7 
  8 int n,m;
  9 #define maxn 1011
 10 #define maxm 12011*2
 11 struct Edge{int from,to,next,cap,flow;};
 12 const int inf=0x7fffffff;
 13 struct Network
 14 {
 15     Edge edge[maxm];int n,s,t,le;
 16     int first[maxn],dis[maxn],cur[maxn];
 17     void clear(int n)
 18     {
 19         memset(first,0,sizeof(first));
 20         le=2;this->n=n;
 21     }
 22     void add_edge(int x,int y,int v)
 23     {
 24         Edge &e=edge[le];
 25         e.to=y;e.from=x;
 26         e.cap=v;e.flow=0;
 27         e.next=first[x];
 28         first[x]=le++;
 29     }
 30     void insert(int x,int y,int v)
 31     {
 32         add_edge(x,y,v);
 33         add_edge(y,x,0);
 34     }
 35     int que[maxn],head,tail;
 36     bool bfs()
 37     {
 38         memset(dis,0,sizeof(dis));
 39         dis[s]=1;
 40         que[head=(tail=1)-1]=s;
 41         while (head!=tail)
 42         {
 43             const int x=que[head++];
 44             for (int i=first[x];i;i=edge[i].next)
 45             {
 46                 Edge &e=edge[i];
 47                 if (e.cap>e.flow && !dis[e.to])
 48                 {
 49                     dis[e.to]=dis[x]+1;
 50                     que[tail++]=e.to;
 51                 }
 52             }
 53         }
 54         return dis[t];
 55     }
 56     int dfs(int x,int a)
 57     {
 58         if (x==t || !a) return a;
 59         int flow=0,f;
 60         for (int &i=cur[x];i;i=edge[i].next)
 61         {
 62             Edge &e=edge[i];
 63             if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0)
 64             {
 65                 flow+=f;
 66                 a-=f;
 67                 e.flow+=f;
 68                 edge[i^1].flow-=f;
 69                 if (!a) break;
 70             }
 71         }
 72         return flow;
 73     }
 74     int Dinic(int s,int t)
 75     {
 76         this->s=s;this->t=t;
 77         int ans=0;
 78         while (bfs())
 79         {
 80             for (int i=1;i<=n;i++) cur[i]=first[i];
 81             ans+=dfs(s,inf);
 82         }
 83         return ans;
 84     }
 85 }G;
 86 int x,y;
 87 int main()
 88 {
 89     scanf("%d%d",&n,&m);
 90     G.clear(n*2+2);
 91     int s=n*2+1,t=s+1;
 92     for (int i=1;i<=m;i++)
 93     {
 94         scanf("%d%d",&x,&y);
 95         G.insert(x,y+n,1);
 96     }
 97     for (int i=1;i<=n;i++) G.insert(s,i,1);
 98     for (int i=1;i<=n;i++) G.insert(i+n,t,1);
 99     printf("%d\n",G.Dinic(s,t));
100     return 0;
101 }
View Code

 

posted @ 2017-07-28 16:22  Blue233333  阅读(193)  评论(0编辑  收藏  举报