ZOJ2616 Duopoly 最小割


很明显的最小割

不同公司订单分别连源点和汇点,容量是定价

然后冲突订单连边。容量INF

然后总和减去最小割就是答案


Duopoly

Time Limit: 10 Seconds       Memory Limit: 32768 KB

THE 30th ACM/ICPC ASIA REGIONAL 2005 HANGZHOU SITE

Onsite Contest Session

Problem D: Duopoly

The mobile network market in country XYZ used to be dominated by two large corporations, XYZ Telecom and XYZ Mobile. The central government recently has realized that radio frequency spectrum is a scarce resource and wants to regulate its usage. The spectrum currently in use is divided into 300,000 channels. Any wireless service provider who wishes to use certain spectrum should apply for licenses on these channels. While some services may require use of multiple channels, a single channel can not be shared by different services.

The central government wants to maximize its revenue from the spectrum by putting the channels up to an auction. The only two bidders are XYZ Telecom and XYZ Mobile. They are allowed to place bids on combinations of channels, through which their services can communicate with the customers. Furthermore, the government stipulates that a company can only place at most one bid on a specific channel.

The government can only accept a subset of the bids so none of them would conflict with each other. However, officials soon find out that it is a difficult task to determine the winning bids in order to maximize the revenue, and they are asking for your help.

Input Description

Standard input will contain multiple test cases. The first line of the input is a single integer T (1 <= T <= 10) which is the number of test cases. T test cases follow, each preceded by a single blank line.

Each test case has two bid description sections, which are for XYZ Telecom and XYZ Mobile, respectively. Each section starts with an integer N (1 <= N <= 3,000), which is the number of bids that follow. The next N lines each contain the description for one bid, the first integer P (1 <= P <= 1,000) gives the price of that bid, followed by the channel numbers required by this service. A service would require at least 1 channel and at most 32 channels. Each channel number is a positive integer and will never exceed 300,000.

Output Description

Results should be directed to standard output. Start each case with "Case #:" on a single line, where # is the case number starting from 1. Two consecutive cases should be separated by a single blank line. No blank line should be produced after the last test case.

For each test case, print the maximized revenue the government is able to collect by issuing licenses on the channels.

Sample Input

2

3
45 1
51 2
62 3
4
54 1
15 2
33 3
2 4 5

5
20 1
18 2
23 4
54 3 5 6
17 7
4
36 1 2 3
28 5
47 4 7
16 6

Sample Output

Case 1:
169

Case 2:
139

#include<iostream>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<string>

using namespace std;

#define MAXN 10000
#define INF 0xFFFFFF

struct edge
{
	int to,c,next;
};

edge e[999999];
int que[MAXN*100];
int dis[MAXN];
int pre[MAXN];
int head[MAXN],head2[MAXN];
int st,ed,maxflow,en;

void add(int a,int b,int c)
{
	e[en].to=b;
	e[en].c=c;
	e[en].next=head[a];
	head[a]=en++;
	e[en].to=a;
	e[en].c=0;
	e[en].next=head[b];
	head[b]=en++;
}

bool bfs()
{
	memset(dis,-1,sizeof(dis));
	que[0]=st,dis[st]=1;
	int t=1,f=0;
	while(f<t)
	{
		int j=que[f++];
		for(int k=head[j];k!=-1;k=e[k].next)
		{
			int i=e[k].to;
			if(dis[i]==-1 && e[k].c)
			{
				que[t++]=i;
				dis[i]=dis[j]+1;
				if(i==ed) return true;
			}
		}
	}
	return false;
}

int update()
{
	int p,flow=INF;
    for (int i=pre[ed];i!=-1;i=pre[i])
		if(e[head2[i]].c<flow) p=i,flow=e[head2[i]].c;
    for (int i=pre[ed];i!=-1;i=pre[i])
		e[head2[i]].c-=flow,e[head2[i]^1].c+=flow;
    maxflow+=flow;
    return p;
}

void dfs()
{
	memset(pre,-1,sizeof(pre));
	memcpy(head2,head,sizeof(head2));
    for(int i=st,j;i!=-1;)
    {
        int flag=false;
        for(int k=head[i];k!=-1;k=e[k].next)
          if(e[k].c && (dis[j=e[k].to]==dis[i]+1) )
          {
                pre[j]=i;
				head2[i]=k;
				i=j;
				flag=true;
                if(i==ed)
					i=update();
                if(flag)
					break;
          }
        if (!flag) dis[i]=-1,i=pre[i];
    }
}

int dinic()
{
	maxflow=0;
	while(bfs())
		dfs();
	return maxflow;
}

int sum,n1,n2;
int type[300010];
char str[1000];

int main()
{
    int cs;
    scanf("%d",&cs);
    for(int css=1;css<=cs;css++)
    {
        if(css!=1) printf("\n");
        sum=0;st=0;
        memset(head,-1,sizeof(head));en=0;
        memset(type,0,sizeof(type));
        scanf("%d",&n1);
        for(int i=1;i<=n1;i++)
        {
            int p;
            scanf("%d",&p);
            sum+=p;
            add(st,i,p);
            gets(str);
            stringstream ss(str);
            while(ss>>p) type[p]=i;
        }
        scanf("%d",&n2);
        ed=n1+n2+1;
        for(int i=n1+1;i<=n1+n2;i++)
        {
            int p;
            scanf("%d",&p);
            sum+=p;
            add(i,ed,p);
            gets(str);
            stringstream ss(str);
            while(ss>>p) if(type[p]) add(type[p],i,INF);
        }
        dinic();
        printf("Case %d:\n",css);
        printf("%d\n",sum-maxflow);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值