P3623 [APIO2008] 免费道路
P3623 [APIO2008] 免费道路
题目翻译:
给定一个无向联通图,图中的边有两种类型
思路:
阅读题目发现,最后的图要是一棵树,使得上面边为
无解判定:
1.若第一次跑
2.若第二次跑完
完整代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int fa[N];
int n,m,k,cnt;
struct edge{
int u,v,w;
}e[N];
bool cmp1(edge x,edge y){
return x.w<y.w;
}
bool cmp2(edge x,edge y){
return x.w>y.w;
}
int find(int x){
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]);
}
void kruskal1(){
for(int i=1;i<=n;i++){
fa[i]=i;
}
sort(e+1,e+1+m,cmp1);
for(int i=1;i<=m;i++){
int u=find(e[i].u);
int v=find(e[i].v);
if(u!=v){
fa[u]=v;
if(e[i].w==1){
cnt++;
e[i].w=3;
}
}
}
if(cnt>k){
cout<<"no solution"<<endl;
exit(0);
}
}
void kruskal2(){
int num=0;
for(int i=1;i<=n;i++){
fa[i]=i;
}
sort(e+1,e+1+m,cmp2);
for(int i=1;i<=m;i++){
int u=find(e[i].u);
int v=find(e[i].v);
if(find(u)!=find(v)){
if(e[i].w==1 && cnt==k){
continue;
}
num++;
fa[u]=v;
if(e[i].w==1 && cnt<k){
e[i].w=3;
cnt++;
}
else if(e[i].w==0){
e[i].w=-2;
}
}
}
if(num<n-1 || cnt<k){
cout<<"no solution"<<endl;
exit(0);
}
for(int i=1;i<=m;i++){
if(e[i].w==3)cout<<e[i].u<<" "<<e[i].v<<" "<<0<<endl;
if(e[i].w==-2)cout<<e[i].u<<" "<<e[i].v<<" "<<1<<endl;
}
}
signed main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
w=!w;
e[i]={u,v,w};
}
kruskal1();
kruskal2();
}