hdu 3879 Base Station

  1 做得还算麻利~
  2 /*最大闭合子图
  3 题意:建通讯站。每个通讯站有一定耗费,两个特定的通讯站之间建立通讯以后
  4 会有一定收益,问怎样建立通讯站可以使得收益最大 。
  5 ——最大权闭合子图->最小割
  6 ——url:http://acm.hdu.edu.cn/showproblem.php?pid=3879
  7 思路:
  8 首先考虑将图转化。
  9 即一条通讯线路有一定收益wi(即为正点权),但需要建立两个通讯站,
 10 这两个通讯站有一定造价pi(即为负点权)。
 11 将通讯线路也变成点,点权为收益,连两条有向只向两个通讯站。
 12 原来的通讯站点权不变。则start=0;end=m+n+1;totals=end+1;
 13 由此,题目转化为在新的图中求一个闭合图,使得其点权最大,即最大权闭合子图
 14 具体见图如下:
 15 建一个源点Start,与每个通讯线路的点相连,边权为收益
 16 建一个汇点end,end与每个通讯站相连,边权为建造费用
 17 通讯站与通讯线路之间的边权为无穷大
 18 最后的结果为所有通讯线路总的收益-最小割(最大流)
 19 */ 
 20 #include <iostream>
 21 #include<cstdio>
 22 #include<cstring>
 23 #include<vector>
 24 #include<queue>
 25 #include<algorithm>
 26 using namespace std;
 27 #define min(a,b) ((a)<(b))?(a):(b)
 28 #define max(a,b) ((a)>(b))?(a):(b)
 29 #define MAXN  60000//这里取略大于m+n+2的值(500+50000+2)所以这里取60000否则会runtime error 
 30 #define MAXM 5400000//M取N的平方倍或者N*9
 31 #define INF 0x3f3f3f3f
 32 
 33 struct node
 34 {
 35     int n;//点编号
 36     int w;//点权
 37 }Node[MAXN];
 38 //链式前向星
 39 struct enode
 40 {
 41     int t;
 42     int w;                //权值
 43     int c;                //流量
 44 //  int cost;
 45 //    int pre;            //前向指针
 46     int next;
 47 };
 48 
 49 
 50     struct enode e[MAXM];
 51     int box[MAXN],ecnt;
 52     //int etail[MAXN];        //尾部
 53     void init()
 54     {
 55         ecnt=0;
 56         memset(box,-1,sizeof(box));
 57     //    memset(etail,-1,sizeof(etail));        //初始化尾部
 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 main()
129 {
130      int m,n,a,b,c,t,w;
131      int i,j,k;
132      int start,end,ans;
133   while(scanf("%d%d",&n,&m)!=EOF)  //;
134    {
135         //scanf("%d%d",&n,&m);
136         start=ans=0;
137         end=n+m+1;
138         init();
139         for(i=1;i<=n;i++)
140         {
141             scanf("%d",&w);
142             addedge(i+m,end,w);//终点和负点权边相连
143 
144         }
145         for(i=1;i<=m;i++)
146         {
147             scanf("%d%d%d",&a,&b,&c);//正点权
148             ans+=c;
149             addedge(i,b+m,INF);//建图关键
150             addedge(i,a+m,INF);//建图关键
151             addedge(start,i,c);
152         }
153         t=sap( start,end,end+1);//*/
154         printf("%d\n",ans-t);
155    }
156     return 0;
157 }
158 /*
159 Sample Input
160 
161 5 5
162 1 2 3 4 5
163 1 2 3
164 2 3 4
165 1 3 3
166 1 4 2
167 4 5 3
168 
169 Sample Output
170 
171 2
172 */

 

posted on 2013-04-22 21:19  ACM_Someone like you  阅读(224)  评论(0编辑  收藏  举报

导航