HDU2485 Destroying the bus stations (POJ3921)

  1 /*
  2 题意:军队坐bus去机场 n个节点(bus)m条公交通路(单向)
  3 每走一条路花时间1 问最少破坏几个结点(是相关联的的路都不能走)
  4 使军队在至少k时间不能到达机场。
  5 思路:求最小割(等于最大流)
  6 建(新)图:弗洛伊德求出任意两点最短路(dist[a][b])
  7 核心判断dist(1,a)+dist(b,n)之和满足小于k 则建边addedge(n+a,b,INF)
  8 
  9 addedge(i,i+n,1);//注意方向
 10 
 11 start=n+1,end=n;totals=n+n;
 12 sap();即可。
 13 */
 14 #include <iostream>
 15 #include<cstdio>
 16 #include<cstring>
 17 #include<vector>
 18 #include<queue>
 19 #include<algorithm>
 20 using namespace std;
 21 #define min(a,b) ((a)<(b))?(a):(b)
 22 #define max(a,b) ((a)>(b))?(a):(b)
 23 #define MAXN 6005//尽量开大点
 24 #define MAXM  100002 //M取N的平方倍或者N*9
 25 #define INF 0x3f3f3f3f
 26 int m,n;
 27 struct node
 28 {
 29     int n;//点编号
 30     int w;//点权
 31 }Node[MAXM];//n变m
 32 
 33 //链式前向星
 34 struct enode
 35 {
 36     int t;
 37     int w;                //权值
 38     int c;                //流量
 39 //  int cost;
 40 //    int pre;            //前向指针
 41     int next;
 42 };
 43 
 44     struct enode e[MAXM];
 45     int box[MAXN],ecnt;
 46     //int etail[MAXN];        //尾部
 47     void init()
 48     {
 49         ecnt=0;
 50         memset(box,-1,sizeof(box));
 51     //    memset(etail,-1,sizeof(etail));        //初始化尾部
 52     }
 53     void add(int s,int t)
 54     {
 55          e[ecnt].t=t;
 56          e[ecnt].next=box[s];
 57          box[s]=ecnt++;
 58     }
 59     void addedge(int f,int t,int c)            //流量重载
 60     {
 61         e[ecnt].next=box[f];
 62         e[ecnt].t=t;
 63         e[ecnt].c=c;
 64         box[f]=ecnt++;
 65         e[ecnt].next=box[t];
 66         e[ecnt].t=f;
 67         e[ecnt].c=0;
 68         box[t]=ecnt++;
 69     }
 70 int sap(int s,int t,int N)//最大流问题
 71 {
 72     int gap[MAXN],lvl[MAXN],cur[MAXN],pre[MAXN];
 73     int curflow,ans=0,u,tmp,neck,i;
 74     memset(lvl,0,sizeof(lvl));
 75     memset(gap,0,sizeof(gap));
 76     memset(pre,-1,sizeof(pre));
 77     for(i=0;i<N;i++)
 78         cur[i]=box[i];
 79     gap[0]=N;
 80     u=s;
 81     while(lvl[s]<N)
 82     {
 83         if(u==t)
 84         {
 85             curflow=INF;
 86             for(i=s;i!=t;i=e[cur[i]].t)
 87             {
 88                 if(curflow>e[cur[i]].c)
 89                 {
 90                     neck=i;
 91                     curflow=e[cur[i]].c;
 92                 }
 93             }
 94             for(i=s;i!=t;i=e[cur[i]].t)
 95             {
 96                 tmp=cur[i];
 97                 e[tmp].c-=curflow;
 98                 e[tmp^1].c+=curflow;
 99             }
100             ans+=curflow;
101             u=neck;
102         }
103         for(i=cur[u];i!=-1;i=e[i].next)
104             if(e[i].c && lvl[u]==lvl[e[i].t]+1)
105                 break;
106         if(i!=-1)
107         {
108             cur[u]=i;
109             pre[e[i].t]=u;
110             u=e[i].t;
111         }
112         else
113         {
114             if(--gap[lvl[u]]==0)
115                 break;
116              cur[u]=box[u];
117             for(tmp=N,i=box[u];i!=-1;i=e[i].next)
118                 if(e[i].c)
119                     tmp=min(tmp,lvl[e[i].t]);
120             lvl[u]=tmp+1;
121             gap[lvl[u]]++;
122             if(u!=s)
123                 u=pre[u];
124         }
125     }
126     return ans;
127 }
128 int dist[100][100];
129 int index[100][100];
130 void f()
131 {
132     int i,j,k;
133     for(i=1;i<=n;i++)
134     {
135         for(j=1;j<=n;j++)
136         {
137             for(k=1;k<=n;k++)
138             {
139                 if(dist[j][k]>dist[j][i]+dist[i][k]&&(j!=k))
140                 dist[j][k]=dist[j][i]+dist[i][k];
141             //松弛dist
142             }
143         }
144     }
145 }
146 int main()
147 {
148      int a,b,c,d,t,k,w,ct;
149      int i,j;
150      int start,end,ans;
151    while(scanf("%d%d%d",&n,&m,&k)&&n&&m&&k)
152    {
153        start=0;
154        end=n;
155        init();
156        memset(dist,INF,sizeof(dist));
157        memset(index,0,sizeof(index));
158        for(i=1;i<=n;i++)dist[i][i]=0;
159        for(i=1;i<=m;i++)
160        {
161            scanf("%d%d",&a,&b);
162            dist[a][b]=1;
163            index[a][b]=1;//标记通路索引
164        }
165        f();
166        for(i=1;i<=n;i++)
167        {
168            for(j=1;j<=n;j++)
169            {
170                if(index[i][j])//如果i 到 j是通路
171                {
172                    if(dist[1][i]+dist[j][n]<k)//该边两端的dist小于k
173                    addedge(i+n,j,INF);//流设为最大(未来应该可能被破坏的)
174                }//建立连接新节点 建新图
175            }
176        }
177       for(i=1;i<=n;i++)addedge(i,i+n,1);//建新图相连接的两个节点流量为1
178       // printf("%d---->%d\n",i,dist[i][j]);
179       ans=sap(n+1,end,n*2);
180       if(ans>n)printf("%d\n",n);
181       else
182        printf("%d\n",ans);
183    }
184     return 0;
185 }
186 /*
187 
188 Sample Input
189 
190 5 7 3
191 1 3
192 3 4
193 4 5
194 1 2
195 2 5
196 1 4
197 4 5
198 0 0 0
199 
200 Sample Output
201 
202 2
203 */
原文地址:https://www.cnblogs.com/someonelikeyou/p/3038594.html