南邮 OJ 1656 通讯站建设
2015-08-06 10:29
183 查看
通讯站建设
时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte总提交 : 60 测试通过 : 23
比赛描述
YM同学调查得知:新的技术正冲击着手机通讯市场,南京移动公司准备新建一些通讯站,它们一共得到N个可以作为通讯站的数据,其中中建立第i个通讯站需要成本Pi。另外,公司得到M条用户群信息,第i个用户群会使用通讯站Ai和Bi进行通信,公司将获利Ci(1≤i≤M, 1≤Ai, Bi≤N)。公司选择建立一些通讯站(投入成本),为一些用户群提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)
输入
多组输入数据。
每组数据第一行有2个正整数N和M。第二行中有N个整数描述每一个通讯中转站的建立成本,依次为P1, P2, …, PN 。接下来M行,第(i + 2)行的三个数Ai, Bi和Ci描述第i个用户群的信息。(N≤12,M≤50,0≤Ci≤100,0≤Pi≤100。)
输出
每组数据输出一个整数,表示公司可以得到的最大净获利。
样例输入
5 5
1 2 3 4 5
1 2 3
2 3 4
1 3 3
1 4 2
4 5 3
样例输出
4
提示
样例说明:选择建立1、2、3号中转站,则需要投入成本6,获利为10,因此得到最大收益4。
题目来源
ym
/* AC 0MS Internet #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> using namespace std; const int MAXN=55003,MAXM=(50001*3+5001)*2,INF=200; struct edge { edge *next,*op; int t,c; }*V[MAXN],*P[MAXN],ES[MAXM],*Stae[MAXN]; int N,M,S,T,Ans,EC; int Lv[MAXN],Stap[MAXN]; inline void addedge(int a,int b,int c) { ES[++EC].next=V[a]; V[a]=ES+EC; V[a]->t=b; V[a]->c=c; ES[++EC].next=V[b]; V[b]=ES+EC; V[b]->t=a; V[b]->c=0; V[a]->op=V[b]; V[b]->op=V[a]; } void init() { int i,a,b,c; S=0; T=N+M+1; for (i=1;i<=N;i++) { scanf("%d",&c); addedge(i+M,T,c); } for (i=1;i<=M;i++) { scanf("%d%d%d",&a,&b,&c); addedge(i,a+M,INF); addedge(i,b+M,INF); addedge(S,i,c); Ans += c; } } bool level() { int head=0,tail=-1,i,j; memset(Lv,0,sizeof(Lv)); Lv[S]=1; Stap[++tail]=S; while (head<=tail) { i=Stap[head++]; for (edge *e=V[i];e;e=e->next) { if (e->c && !Lv[j=e->t]) { Lv[j]=Lv[i]+1; Stap[++tail]=j; if (j==T) return true; } } } return false; } int augment() { int i,j,delta,flow=0,Stop=1; for (i=S;i<=T;i++) P[i]=V[i]; Stap[Stop]=S; while (Stop) { i=Stap[Stop]; if (i!=T) { for (;P[i];P[i]=P[i]->next) if (P[i]->c && Lv[j=P[i]->t] == Lv[i] + 1) break; if (P[i]) { Stap[++Stop]=j; Stae[Stop]=P[i]; } else { Stop--; Lv[i]=0; } } else { delta=INF; for (i=Stop;i>=2;i--) if (Stae[i]->c < delta) delta = Stae[i]->c; flow += delta; for (i=Stop;i>=2;i--) { Stae[i]->c -=delta; Stae[i]->op->c +=delta; if (Stae[i]->c == 0) Stop=i-1; } } } return flow; } void dinic() { int Maxflow; for (Maxflow=0;level();) Maxflow += augment(); Ans -= Maxflow; } int main() { while(scanf("%d%d",&N,&M)==2){ Ans = 0; init(); dinic(); printf("%d\n",Ans); } return 0; } */ /* AC 0MS Internet #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define inf 1000000000 int n,m,t,sum,l; struct node { int u,v,c,next; }edge[240000]; int head[240000]; int d[60000],sumd[60000]; void add(int u,int v,int c){ edge[l].u=u; edge[l].v=v; edge[l].c=c; edge[l].next=head[u]; head[u]=l++; edge[l].u=v; edge[l].v=u; edge[l].c=0; edge[l].next=head[v]; head[v]=l++; } int sap(int u,int flow){ if(u==t){ return flow; } int res=0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(edge[i].c && d[u]==d[v]+1){ int tmp=sap(v,min(edge[i].c,(flow-res))); res+=tmp; edge[i].c-=tmp;edge[i^1].c+=tmp; if(res==flow){ return res; } if(d[0]>=t+1){ return res; } } } sumd[d[u]]--; if(sumd[d[u]]==0){ d[0]=t+1; } sumd[++d[u]]++; return res; } int main(){ while(scanf("%d%d",&n,&m)==2){ sum = l = 0; int x; t=n+m+1; memset(head,-1,sizeof(head)); memset(d,0,sizeof(d)); memset(sumd,0,sizeof(sumd)); for(int i=1;i<=n;i++){ scanf("%d",&x); add(i,t,x); } for(int i=1;i<=m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); add(i+n,a,inf); add(i+n,b,inf); add(0,i+n,c); sum+=c; } int ans=0; sumd[0]=t+1; while(d[0]<=t){ ans+=sap(0,inf); } printf("%d\n",sum-ans); } }
相关文章推荐
- 诚信
- iOS架构网址
- 动态规划_线性结构上的DP
- SQLAlchemy文档翻译第1章
- lnmp环境的搭建
- Erlang application stop 调用死锁
- Android 判断用户2G/3G/4G移动数据网络
- Erlang application stop 调用死锁
- ROS学习--(十七)turtlebot的安装
- Writing Resources
- VC++2010 MFC程序怎么在其他电脑运行
- 最短路(spfa)
- Linux命令-下载文件的工具:wget
- 解析Java中的队列和用LinkedList集合模拟队列的方法
- Linux下mysql主从配置
- 利用hyper-v部署测试环境-兰晓宇-专题视频课程
- 阅读订阅网站抓虾已宣布关站
- nyoj-19 擅长排列的小明 (dfs)
- 细数二十世纪最伟大的10大算法
- 南邮 OJ 1654 集训