poj2987 Firing

  以前只是A过很简单的最大闭合权像hdu1565之类,完全的最大流模板题。但是都完全不太懂最大闭合权的定义及其用途。

 关于最大流的基础知识,大家可以自己网上搜索关键字。有点基础的哥们妹们,推荐看看胡伯涛最小割模型在信息学竞赛中的应用》,里面除了很多理论知识以外还有很多不错题集,大家可以练练。

 最大闭合权,是最大流一个很经典的应用,关键字:闭合图最大闭合权。

 这种题目表现的模型通常是A-->B-->C,即A事件发生,其后续事件也一定要发生。

 如果每个事件发生都有一个效益值的,用最大流算法便可以求出这种效益的最值。

 

 这个题目的另外一个问题是要求删掉的最少点数,乍一看好像很陌生,但是,大家不妨自己举个例子就可以发现这个就是传说中——最简的 、最小割集!

 最小割集固然是可能有很多个的,分割的位置便是网络中满流的位置。

 这道题求最简的最小割,那就是从源点开始,遍历所有可行边所访问的点集!

 帖个水水的代码,希望没有寒碜到大家。WA了n多次,后来发现是计算最大流函数的返回值忘了改成lli。我的钛合金**眼啊!!!!

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 typedef long long lli;
  6 const int maxn = 5010;
  7 const int maxe = 400100;
  8 const lli maxf = 1LL<<50;
  9 #define smaller(a,b) ((a)<(b)?(a):(b))
 10 struct edge{
 11        int u,v;
 12        lli c;
 13        edge(int a=0,int b=0,lli d=0){ u=a, v=b, c=d; }
 14 }e[maxe];
 15 int head[maxn];
 16 int next[maxe];
 17 int cnt;
 18 void add(int u,int v,lli c){
 19      e[cnt] = edge(u,v,c);
 20      next[cnt] = head[u], head[u] = cnt++;
 21      //printf("cnt = %d,\t%d --> %d with c = %d, next = %d\n",cnt-1,u,v,c,next[cnt-1]);
 22      e[cnt] = edge(v,u,0);
 23      next[cnt] = head[v], head[v] = cnt++;
 24 }
 25 //*****//
 26 int source,sink,maxdep;
 27 int dep[maxn],gap[maxn];
 28 int cur[maxn],trace[maxn],que[maxn],top;
 29 void setGD(){
 30      for(int i=0;i<=maxdep;i++) dep[i] = maxdep;
 31      dep[sink] = 0;
 32      memset(gap,0,sizeof(gap));
 33      gap[dep[sink]] = 1;
 34      gap[maxdep] = maxdep;
 35      int front,rear,u,v;
 36      front = rear = 0;
 37      que[rear++] = sink;
 38      while(front != rear){
 39            u = que[front++];
 40            if(front >= maxn) front = 0;
 41            for(int i=head[u];i!=-1;i=next[i]){
 42                  v = e[i].v;
 43                  if(e[i].c>0 || dep[v] <= dep[u]+1) continue;
 44                  dep[v] = dep[u]+1;
 45                  gap[dep[v]]++;
 46                  que[rear++] = v;
 47                  if(rear >= maxn) rear = 0;
 48            }
 49      }
 50 }
 51 lli maxF(){
 52     setGD();
 53     for(int i=0;i<=maxdep;i++) cur[i] = head[i];
 54     int u=source,i;
 55     top = 0;
 56     lli flow = 0;
 57     while(dep[source] <= maxdep){
 58         if(u == sink){
 59              lli tf = maxf;
 60              int ins;
 61              for(i=0;i<top;i++){ //找瓶颈边
 62                 if(tf > e[trace[i]].c){
 63                       tf = e[trace[i]].c;
 64                       ins = i;
 65                 }
 66              }
 67              /*
 68              for(i=0;i<top;i++)
 69                 printf("%d -> ",e[trace[i]].u);
 70              printf("%d , temp_flow = %d\n",e[trace[top-1]].v,tf);
 71              */
 72              for(i=0;i<top;i++){
 73                 e[trace[i]].c -= tf;
 74                 e[trace[i]^1].c += tf;
 75              }
 76              flow += tf;
 77              u = e[trace[ins]].u, top = ins;
 78         }
 79         if(u != sink && gap[dep[u]-1]==0) break;
 80         for(i=cur[u];i!=-1;i=next[i])
 81              if(e[i].c > 0 && dep[u] == dep[e[i].v] + 1)
 82                        break;
 83         if(i != -1) {
 84              trace[top++] = i;
 85              cur[u] = i;
 86              u = e[i].v;
 87         }
 88         else {
 89              int mindep = maxdep;
 90              for(i=head[u];i!=-1;i=next[i]){
 91                  if(e[i].c > 0 && dep[e[i].v] < mindep)
 92                            mindep = dep[e[i].v], cur[u] = i;
 93              }
 94              gap[dep[u]]--;
 95              dep[u] =  mindep + 1;
 96              gap[dep[u]]++;
 97              if(u != source)
 98                 u = e[trace[--top]].u;
 99         }
100     }
101     return flow;
102 }
103 //**********************//
104 int visited[maxn];
105 int value[maxn];
106 void initial()
107 {
108      cnt = 0;
109      memset(head,-1,sizeof(head));
110      memset(visited,0,sizeof(visited));
111      //initial source ,sink and maxdep;
112 }
113 int era;
114 void search(int u){
115     //cout<<"u = "<<u<<endl;
116     visited[u] = 1;
117     era++;
118     for(int i=head[u];i>=0;i=next[i])
119     if(!visited[e[i].v] && e[i].c)
120         search(e[i].v);
121 }
122 int main()
123 {
124     int n,m;
125     while(scanf("%d%d",&n,&m) != EOF){
126         lli sum = 0;
127         int u,v,c;
128         initial();
129         source=0,sink=n+2,maxdep=sink+2;
130         for(int i=1;i<=n;i++){
131             scanf("%d",&c);
132             value[i] = c;
133             if(c > 0) add(source,i,c), sum+=c;
134             else if(c < 0) add(i,sink,-c);
135         }
136         for(int i=0;i<m;i++)
137             scanf("%d%d",&u,&v), add(u,v,maxf);
138         lli ret = maxF();
139         //if(ret >= sum) puts("0 0");  else {
140             era = 0;
141             search(source);
142             cout<<(era-1)<<" "<<(sum-ret)<<endl;
143         //}
144     }
145     return 0;
146 }
View Code

 

posted on 2013-07-29 20:09  男神发量  阅读(267)  评论(0编辑  收藏  举报