HDU 4253 最小生成树+二分
Two Famous Companies
Time Limit: 50000/15000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 407 Accepted Submission(s): 116
Problem Description
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.
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.
Input
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.
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.
Output
For each test case, display the case number and the minimum cost of the cable building.
Sample Input
2 2 1 0 1 1 1 0 1 2 0 2 2 0 0 1 1 1 0 1 2 0
Sample Output
Case 1: 2 Case 2: 1HintIn 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.
题意:有中国移动和中国联通要为n个城市提供服务,已知m条路线,求中国移动选择k条路的最小生成树。
解题思路:以其中一个作为参考对象,A ,B ,给A中每一条路加一个Delta值,然后求最下生成树,根据二分Delta来选择Delta的合适值。
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=60000;
const int inf=49999990;
int pre[maxn],cnt1,cnt2,ans,m,n,k;
struct node
{
int from,to,len;
}s1[maxn*4],s2[4*maxn];
bool cmp(node a,node b)
{
return a.len<b.len;
}
int find(int x)
{
if(pre[x]!=x)pre[x]=find(pre[x]);
return pre[x];
}
bool fun(int mid)
{
int i,j;
for(i=0;i<=n;i++)pre[i]=i;
i=j=0;
int num=0;
while(i<cnt1&&j<cnt2)
{
if(s1[i].len+mid<=s2[j].len)
{
int fa=find(s1[i].from);
int fb=find(s1[i].to);
if(fa!=fb)
{
ans+=s1[i].len+mid;
pre[fa]=fb;
num++;
}
i++;
}
else
{
int fa=find(s2[j].from);
int fb=find(s2[j].to);
if(fa!=fb)
{
ans+=s2[j].len;
pre[fa]=fb;
}
j++;
}
}
while(i<cnt1)
{
int fa=find(s1[i].from);
int fb=find(s1[i].to);
if(fa!=fb)
{
ans+=s1[i].len+mid;
pre[fa]=fb;
num++;
}
i++;
}
while(j<cnt2)
{
int fa=find(s2[j].from);
int fb=find(s2[j].to);
if(fa!=fb)
{
ans+=s2[j].len;
pre[fa]=fb;
}
j++;
}
return num>=k;
}
int main()
{
int i,j,ncase=0;
while(~scanf("%d%d%d",&n,&m,&k))
{
cnt1=0,cnt2=0;
while(m--)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(d==0)
{
s1[cnt1].from=a;
s1[cnt1].to=b;
s1[cnt1++].len=c;
}
else
{
s2[cnt2].from=a;
s2[cnt2].to=b;
s2[cnt2++].len=c;
}
}
sort(s1,s1+cnt1,cmp);
sort(s2,s2+cnt2,cmp);
int left=-100,right=100,mid;
int sum;
while(left<right)
{
int mid=(left+right+1)>>1;
ans=0;
int tt=fun(mid);
if(tt)left=mid;
else right=mid-1;
}
ans=0;
fun(left);
printf("Case %d: %d\n",++ncase,ans-k*left);
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=60000;
const int inf=49999990;
int pre[maxn],cnt1,cnt2,ans,m,n,k;
struct node
{
int from,to,len;
}s1[maxn*4],s2[4*maxn];
bool cmp(node a,node b)
{
return a.len<b.len;
}
int find(int x)
{
if(pre[x]!=x)pre[x]=find(pre[x]);
return pre[x];
}
bool fun(int mid)
{
int i,j;
for(i=0;i<=n;i++)pre[i]=i;
i=j=0;
int num=0;
while(i<cnt1&&j<cnt2)
{
if(s1[i].len+mid<=s2[j].len)
{
int fa=find(s1[i].from);
int fb=find(s1[i].to);
if(fa!=fb)
{
ans+=s1[i].len+mid;
pre[fa]=fb;
num++;
}
i++;
}
else
{
int fa=find(s2[j].from);
int fb=find(s2[j].to);
if(fa!=fb)
{
ans+=s2[j].len;
pre[fa]=fb;
}
j++;
}
}
while(i<cnt1)
{
int fa=find(s1[i].from);
int fb=find(s1[i].to);
if(fa!=fb)
{
ans+=s1[i].len+mid;
pre[fa]=fb;
num++;
}
i++;
}
while(j<cnt2)
{
int fa=find(s2[j].from);
int fb=find(s2[j].to);
if(fa!=fb)
{
ans+=s2[j].len;
pre[fa]=fb;
}
j++;
}
return num>=k;
}
int main()
{
int i,j,ncase=0;
while(~scanf("%d%d%d",&n,&m,&k))
{
cnt1=0,cnt2=0;
while(m--)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(d==0)
{
s1[cnt1].from=a;
s1[cnt1].to=b;
s1[cnt1++].len=c;
}
else
{
s2[cnt2].from=a;
s2[cnt2].to=b;
s2[cnt2++].len=c;
}
}
sort(s1,s1+cnt1,cmp);
sort(s2,s2+cnt2,cmp);
int left=-100,right=100,mid;
int sum;
while(left<right)
{
int mid=(left+right+1)>>1;
ans=0;
int tt=fun(mid);
if(tt)left=mid;
else right=mid-1;
}
ans=0;
fun(left);
printf("Case %d: %d\n",++ncase,ans-k*left);
}
return 0;
}
                    
                
                
            
        
浙公网安备 33010602011771号