zoukankan      html  css  js  c++  java
  • upc2020年秋季组队训练赛第三场问题 I: Two Famous Companies

    问题 I: Two Famous Companies
    时间限制: 1 Sec 内存限制: 128 MB

    题目描述
    In China, there are two companies offering the Internet service for the people from all cities: China Telecom and China Unicom. They both are planning to build cables between cities. Obviously, the government wants to connect all the cities in minimum costs. So the minister of finance Mr. B wants to choose some of the cable plans from the two companies and calculate the minimum cost needed to connect all the cities. Mr. B knows that N-1 cables should be built in order to connect all N cities of China. For some honorable reason, Mr. B should choose K cables from the China Telecom and the rest N-1-K cables from the China Unicom. Your job is to help Mr. B determine which cables should be built and the minimum cost to build them. You may assume that the solution always exists.
    输入
    Each test case starts with a line containing the number of cities N (1 <= N <= 50,000), number of cable plans M (N-1 <= M <= 100,000) and the number of required cables from China Telecom K (0 <= K <= N-1). This is followed by M lines, each containing four integers a, b, c, x (0 <= a, b <= N-1, a != b, 1 <= c <= 100, x in {0,1} indicating the pair of cities this cable will connect, the cost to build this cable and the company this cable plan belongs to. x=0 denotes that the cable plan belongs to China Telecom and x=1 denotes that the cable plan is from China Unicom.
    输出
    For each test case, display the case number and the minimum cost of the cable building.
    样例输入 Copy
    2 2 1
    0 1 1 1
    0 1 2 0
    2 2 0
    0 1 1 1
    0 1 2 0
    样例输出 Copy
    Case 1: 2
    Case 2: 1
    提示
    In the first case, there are two cable plans between the only two cities, one from China Telecom and one from China Unicom. Mr. B needs to choose the one from China Telecom to satisfy the problem requirement even the cost is higher.
    In the second case, Mr. B must choose the cable from China Unicom, which leads the answer to 1.

    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll>PLL;
    typedef pair<int,int>PII;
    typedef pair<double,double>PDD;
    #define I_int ll
    #define x first
    #define y second
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    char F[200];
    inline void out(I_int x) {
        if (x == 0) return (void) (putchar('0'));
        I_int tmp = x > 0 ? x : -x;
        if (x < 0) putchar('-');
        int cnt = 0;
        while (tmp > 0) {
            F[cnt++] = tmp % 10 + '0';
            tmp /= 10;
        }
        while (cnt > 0) putchar(F[--cnt]);
        //cout<<" ";
    }
    ll ksm(ll a,ll b,ll p){ll res=1;while(b){if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;}
    const int inf=0x3f3f3f3f,mod=1e9+7;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const int maxn=1e6+7,maxm=3e5+7;
    const double PI = atan(1.0)*4;
     
    struct Edge{
        int a,b,w,flag;
    };
     
    Edge e[maxn];
    int n,m,k;
    int root[maxn];
     
    void init(){
        for(int i=0;i<=n;i++) root[i]=i;
    }
     
    int Find(int x){
        if(x!=root[x]) root[x]=Find(root[x]);
        return root[x];
    }
     
    bool cmp(Edge a,Edge b){
        if(a.w==b.w) return a.flag<b.flag;
        return a.w<b.w;
    }
     
    ll res=0,sum=0;
     
    bool check(int x){
        sum=0;int cnt=0;
        for(int i=1;i<=m;i++){
            if(!e[i].flag) e[i].w+=x;
        }
        sort(e+1,e+1+m,cmp);
        for(int i=0;i<=n;i++) root[i]=i;
        for(int i=1;i<=m;i++){
            int aa=e[i].a,bb=e[i].b,ww=e[i].w;
            int fa=Find(aa),fb=Find(bb);
            if(fa!=fb){
                sum+=ww;
                root[fa]=fb;
                if(!e[i].flag) cnt++;
            }
        }
        for(int i=1;i<=m;i++){
            if(!e[i].flag) e[i].w-=x;
        }
        if(cnt>=k) return 1;
        return 0;
    }
     
    int main(){
        int Case=1;
        while(cin>>n>>m>>k){
            for(int i=1;i<=m;i++){
                int a=read(),b=read(),w=read(),flag=read();
                e[i]={a,b,w,flag};
            }
            int l=-1000,r=1000;
            while(l<=r){
                int mid=(l+r)/2;
                if(check(mid)){
                    l=mid+1;
                    res=sum-k*mid;
                }
                else{
                    r=mid-1;
                }
            }
            printf("Case %d: %d
    ",Case++,res);
        }
        return 0;
    }
     
     
    
  • 相关阅读:
    C 找到该列最大的前两个数字
    C 寻找和最大的子序列
    C 找出最长的回文子串(不区分大小写)
    C 字符串数组
    C 寻找重复字符并输出他们的位置
    C 寻找0~100的守形数
    C 在外部函数中修改指针变量
    C int转为二进制 再进行与操作
    C 计算阶乘之和
    C 奇偶校验
  • 原文地址:https://www.cnblogs.com/OvOq/p/15073751.html
Copyright © 2011-2022 走看看