您的位置:首页 > 其它

南邮 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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: