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

 

你可能感兴趣的:(poj)