• uva 1212 最大流


    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 

    Standard input will contain multiple test cases. The first line of the input is a single integer T (1$ le$T$ le$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$ le$N$ le$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$ le$P$ le$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 

    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

    参考了众神题解。
    将源点与A公司的bids相连容量分别为price,同理将B公司的与汇点相连。然后从A的bids出发连一条与其冲突的弧到B公司的bids,容量INF,然后最大流即可。
    答案为sum{price}-maxflow。为什么这么做可以呢?
    画个图思考:
    1.A,B无冲突连接,答案正确;
    2.2个属于A的bids与1个B的bid冲突,正确;
    3.2个属于B的bids与1个A的冲突,正确。
    4.不断加点,类似归纳,应该可以证明。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<map>
    
    using namespace std;
    
    #define LL long long
    #define ULL unsigned long long
    #define UINT unsigned int
    #define MAX_INT 0x7fffffff
    #define MAX_LL 0x7fffffffffffffff
    #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
    #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
    #define INF 10000000
    #define MAXN 6010
    #define MAXM 320000
    
    struct edge{
        int u, v, cap, flow, nxt;
    }e[MAXM];
    int h[MAXN], cc;
    
    void add(int u, int v, int cap){
        e[cc]=(edge){u, v, cap, 0, h[u]};
        h[u]=cc++;
        e[cc]=(edge){v, u, 0, 0, h[v]};
        h[v]=cc++;
    }
    
    int p[MAXN], cur[MAXN], d[MAXN];
    
    int vis[MAXN];
    void bfs(int t){
        queue<int> q;   q.push(t);
        memset(vis, 0, sizeof(vis));
        vis[t]=1;   d[t]=0;
        while(!q.empty()){
            int u=q.front();    q.pop();
            for(int i=h[u]; i!=-1; i=e[i].nxt){
                i^=1;
                int v=e[i].u, cap=e[i].cap, ef=e[i].flow;
                if(!vis[v] && cap>ef){
                    vis[v]=1;
                    d[v]=d[u]+1;
                    q.push(v);
                }
                i^=1;
            }
        }
    }
    
    int Augment(int s, int t){
        int u, a=INF;
        for(u=t; u!=s; u=e[p[u]].u)
            a=MIN(a, e[p[u]].cap-e[p[u]].flow);
        for(u=t; u!=s; u=e[p[u]].u){
            e[p[u]].flow+=a;
            e[p[u]^1].flow-=a;
        }
        return a;
    }
    
    int num[MAXN];
    int isap(int s, int t, int n){
        int i, flow=0;
        bfs(t);
        memset(num, 0, sizeof(num));
        for(i=0; i<n; i++) num[d[i]]++;
        for(i=0; i<n; i++) cur[i]=h[i];
        for(int u=s; d[s]<n; ){
            if(u==t){
                flow+=Augment(s, t);
                u=s;
            }
            bool ok=false;
            for(i=h[u]; i!=-1; i=e[i].nxt){
                int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
                if(d[v]+1==d[u] && cap>ef){
                    cur[u]=i;
                    p[v]=i;
                    u=v;
                    ok=true;
                    break;
                }
            }
            if(!ok){
                int tmp=n-1;
                for(i=h[u]; i!=-1; i=e[i].nxt){
                    int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
                    if(cap>ef) tmp=MIN(tmp, d[v]);
                }
                if(--num[d[u]]==0) break;
                num[d[u]=tmp+1]++;
                cur[u]=h[u];
                if(u!=s) u=e[p[u]].u;
            }
        }
        return flow;
    }
    
    int cnt[MAXM];
    int input(int &n3, int f){
        scanf(" %d", &n3);
        int sum=0;
        for(int i=1; i<=n3; i++){
            int p, cha;
            scanf(" %d", &p);
            sum+=p;
    //        int kk=0;
            char ch;
            while((ch=getchar())!='
    ' && ch!=EOF){
                scanf(" %d", &cha);
    //            if(kk++<30) printf(" %d
    ", cha);
                if(cnt[cha]) add(cnt[cha], i+f, INF);
                else cnt[cha]=i+f;
            }
            if(f) add(i+f, f+n3+1, p);
            else add(0, i, p);
        }
        return sum;
    }
    
    int main(){
    //    freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        int T;
        scanf(" %d", &T);
        for(int kase=1; kase<=T; kase++){
            int n1, n2, sum=0;
            memset(cnt, 0, sizeof(cnt));
            memset(h, -1, sizeof(h));       cc=0;
            sum+=input(n1, 0);
            sum+=input(n2, n1);
            sum-=isap(0, n1+n2+1, n1+n2+2);
            if(kase>1) printf("
    ");
            printf("Case %d:
    %d
    ", kase, sum);
        }
        return 0;
    }
    

  • 相关阅读:
    170110-学习MoveIt!
    12.29-ros-gazebo高级
    12.27-ros-gazebo基础
    4.9-Simulation in gazebo or webots
    6.28-机器人模拟器Gazebo基础
    4.8-URDF in ROS
    Win32双缓冲画图原理
    Win32 计时器
    最简化的DirectX 11开发环境的配置 VS2010
    VS2010 C++编译报错LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3351185.html
Copyright © 2020-2023  润新知