题目描述
输入输出格式
输入格式:
在实际评测时,将只会有m-1行公路
输出格式:
输入输出样例
输入样例#1:
4 2 5
1 2 6 5
1 3 3 1
2 3 9 4
2 4 6 1
3 4 4 2
输出样例#1:
4
2 1
3 2
5 1
输入样例#2:
4 1 5
1 2 6 5
1 3 3 1
2 3 9 4
2 4 6 1
3 4 4 3
输出样例#2:
3
2 1
4 2
5 2
思路:最优瓶颈生成树。先跑一遍最下生成树,求出k条1级边,然后对于所有的边排序,求出另外的边。
错因:数组开小了。
80分代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 200000 int n,k,m,tot,fa[MAXN],num,maxn=-1; struct nond{ int a,b,c1,c2,id; }edge[MAXN]; struct none{ int id; int c; }ans[MAXN]; int cmp(nond x,nond y){ return x.c1<y.c1; } int cmp1(nond x,nond y){ return x.c2<y.c2; } int cmp2(none x,none y){ return x.id<y.id; } int find(int x){ if(fa[x]==x) return fa[x]; else return fa[x]=find(fa[x]); } int main(){ scanf("%d%d%d",&n,&k,&m); for(int i=1;i<=m;i++){ int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); edge[++tot].a=a; edge[tot].b=b; edge[tot].c1=c; edge[tot].c2=d; edge[tot].id=i; } sort(edge+1,edge+1+tot,cmp); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=tot;i++){ int dx=find(edge[i].a); int dy=find(edge[i].b); if(dx==dy) continue; fa[dx]=dy; num++; maxn=max(edge[i].c1,maxn); ans[num].id=edge[i].id; ans[num].c=1; if(num==k) break; } sort(edge+1,edge+1+tot,cmp1); for(int i=1;i<=tot;i++){ int dx=find(edge[i].a); int dy=find(edge[i].b); if(dx==dy) continue; fa[dx]=dy; num++; maxn=max(edge[i].c2,maxn); ans[num].id=edge[i].id; ans[num].c=2; if(num==n-1) break; } sort(ans+1,ans+1+num,cmp2); cout<<maxn<<endl; for(int i=1;i<=num;i++) cout<<ans[i].id<<" "<<ans[i].c<<endl; }
AC代码:
#include<cstdio> const int MAXN = 10100; struct Edge{ int x,y,c1,c2; bool p1,p2; }e[50100]; int fa[MAXN]; int n,m,k,ans; int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } bool work(int x) { int cnt = 0; for (int i=1; i<=n; ++i) fa[i] = i; for (int i=1; i<=m; ++i) { e[i].p1 = false ; if (e[i].c1>x) continue ; int rx = find(e[i].x); int ry = find(e[i].y); if (rx!=ry) { cnt++; fa[rx] = ry; e[i].p1 = true; } } if (cnt<k) return false; for (int i=1; i<=m; ++i) { e[i].p2 = false; if (e[i].c2>x) continue ; int rx = find(e[i].x); int ry = find(e[i].y); if (rx!=ry) { cnt++; fa[rx] = ry; e[i].p2 = true; } } if (cnt!=n-1) return false ; return true; } int main() { scanf("%d%d%d",&n,&k,&m); for (int i=1; i<=m; ++i) scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].c1,&e[i].c2); int l = 0, r = 30000; while (l<=r) { int mid = (l+r)>>1; if (work(mid)) { r = mid-1; ans = mid; } else l = mid+1; } work(ans); //重新计算一遍 printf("%d ",ans); for (int i=1; i<=m; ++i) { if (e[i].p1) printf("%d %d ",i,1); if (e[i].p2) printf("%d %d ",i,2); } return 0; }