bzoj3624,[Apio2008]免费道路
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3624
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
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条,若不连通,加马路,这时选的边加上第一遍必须选的边即为答案
代码解释:
q标记的是这次操作是在找答案还是找必须选的鹅卵石的边。b[]记录的是边有没有选,第一次找必加的边的时候只要记录鹅卵石边有没有加,第二次则需要记录所有的边
代码:
#include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> #define N 20010 #define M 100010 using namespace std; struct data{int u,v,c;}a[M]; int fa[N],b[M]; int m,x,y,all,sum,q,k,n; int getint() { int res=0,w=1; char ch=getchar(); while ((ch>'9' || ch<'0')&&ch!='-') ch=getchar(); if (ch=='-') w=-1,ch=getchar(); while (ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar(); return res*w; } int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void add(int p) { for (int i=1;i<=m;i++) { if (a[i].c==p) { x=find(a[i].u); y=find(a[i].v); if (x!=y) { all++; fa[x]=fa[y]; if (q) b[i]=1; if (!p) {b[i]=1; sum++; if (q&&sum==k) return;} } } } } int main() { n=getint(); m=getint(); k=getint(); for (int i=1;i<=m;i++) a[i].u=getint(),a[i].v=getint(),a[i].c=getint(); for (int i=1;i<=n;i++) fa[i]=i; all=0; add(1); add(0); if (all!=n-1||sum>k) {printf("no solution\n"); return 0;} for (int i=1;i<=n;i++) fa[i]=i; sum=0; for (int i=1;i<=m;i++) if (b[i]) sum++,x=find(a[i].u),y=find(a[i].v),fa[x]=y; q=1; if (sum!=k) add(0); add(1); if (sum<k) {printf("no solution\n"); return 0;} for (int i=1;i<=m;i++) if (b[i]) printf("%d %d %d\n",a[i].u,a[i].v,a[i].c); return 0; }
转载请联系博主!!!