AFO

P3623 [APIO2008]免费道路

3624: [Apio2008]免费道路

Time Limit: 2 Sec Memory Limit: 128 MBSec Special Judge
Submit: 2143 Solved: 881
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

5 7 2
1 3 0
4 5 1
3 2 0
5 3 1
4 3 0
1 2 1
4 2 1

Sample Output

3 2 0
4 3 0
5 3 1
1 2 1


先预处理全用水泥路能做到的联通状态
然后处理必须选那些鹅卵石道路才能生成树,这些边标记选择
再随便加有联通贡献鹅卵石路加到k条即可


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;

int i,m,n,j,k,x,y,z,f[100001],c1,c2,bl[500001],cnt1,cnt2;
struct vv
{
    int x,y;
} b[500001],w[500001];

int find(int x)
{
    if(f[x]==x) return x;
    f[x]=find(f[x]);
    return f[x];
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n;i++) f[i]=i;
    
    for(i=1;i<=m;i++) 
    {
        scanf("%d%d%d",&x,&y,&z);
        if(z) { c1+=1; b[c1].x=x, b[c1].y=y;}
        else {c2+=1; w[c2].x=x; w[c2].y=y;}
    }
    if(c2<k) {printf("no solution\n"); return 0;}
    
    for(i=1;i<=c1;i++)	if(find(b[i].x)!=find(b[i].y)) f[f[b[i].x]]=f[b[i].y], cnt1+=1;
    
    if(cnt1<n-1-k) {printf("no solution\n"); return 0;}
    
    for(i=1;i<=c2;i++)	if(find(w[i].x)!=find(w[i].y)) bl[i]=1, f[f[w[i].x]]=f[w[i].y], cnt2+=1;
    
    if(cnt1+cnt2!=n-1) 	{printf("no solution\n"); return 0;}

    for(i=1;i<=n;i++) f[i]=i;  	k-=cnt2;

    for(i=1;i<=c2;i++)
        if(bl[i]) f[find(w[i].x)]=find(w[i].y);
        else if(k && find(w[i].x)!=find(w[i].y)) bl[i]=1, f[f[w[i].x]]=f[w[i].y], k-=1;
        
    if(k) {printf("no solution\n"); return 0;}
    
    for(i=1;i<=c1;i++)
        if(find(b[i].x)!=find(b[i].y)) 
        {
            printf("%d %d 1\n",b[i].x, b[i].y);
            f[f[b[i].x]]=f[b[i].y];
        }
    for(i=1;i<=c2;i++) if(bl[i]) printf("%d %d 0\n",w[i].x,w[i].y);
}
posted @ 2018-10-29 19:50  ZUTTER☮  阅读(180)  评论(0编辑  收藏  举报