3624: [Apio2008]免费道路

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

Description

[Apio2008]免费道路[Kruscal]

Input

[Apio2008]免费道路[Kruscal]

Output

[Apio2008]免费道路[Kruscal]

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

HINT

 

Source

自己的第一次思路:
  小数据枚举k条鹅卵石路,大数据随机找k条鹅卵石路,跟剩下的水泥路构树,如果可以构成树,则此方案可行。
  随机化的阈值我设置的是20.

  然后就砍到72分。

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e4+5;
const int M=1e5+5;
struct edge{int u,v,w,id;}e[M],z[M];
int n,m,num0,K,tot,cct,fa[N],ans[M];
int a[200];bool vis[200];
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline bool cmp(const edge &a,const edge &b){
    return a.id<b.id;
}
inline bool cmp2(const edge &a,const edge &b){
    return a.w<b.w;
}
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void pre(){
    tot=0;ans[0]=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    random_shuffle(e+1,e+num0+1);
    for(int i=1,x,y;i<=num0;i++){
        x=find(e[i].u);y=find(e[i].v);
        if(x!=y){
            fa[y]=x;ans[++ans[0]]=i;
            if(++tot==K) break;
        }
    }
}
inline void ord(){
    tot=0;ans[0]=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1,x,y;i<=K;i++){
        x=find(e[a[i]].u);y=find(e[a[i]].v);
        if(x!=y){
            fa[y]=x;ans[++ans[0]]=a[i];
            if(++tot==K) break;
        }
    }
}
inline void work(){
    for(int i=num0+1,x,y;i<=m;i++){
        x=find(e[i].u);y=find(e[i].v);
        if(x!=y){
            fa[y]=x;ans[++ans[0]]=i;
            if(++tot==n-1) break;
        }
    }
}
inline void print(){
    for(int i=1;i<=ans[0];i++) z[i]=e[ans[i]];
    sort(z+1,z+ans[0]+1,cmp);
    for(int i=1;i<=ans[0];i++) printf("%d %d %d\n",z[i].u,z[i].v,z[i].w);
}
void dfs(int x){
    if(x>K){
        ord();work();
        if(tot==n-1){print();exit(0);}
        return ;
    }
    for(int i=a[x-1]+1;i<=num0;i++){
        if(!vis[i]){
            vis[i]=1;
            a[x]=i;
            if(num0-i<K-x) break;
            dfs(x+1);
            vis[i]=0;
            a[x]=0;
        }
    }
}
int main(){
//    freopen("sh.txt","r",stdin);
    srand(time(0));
    n=read();m=read();K=read();
    for(int i=1;i<=m;i++){
        e[i].u=read(),e[i].v=read(),e[i].w=read(),e[i].id=i;
        if(!e[i].w) num0++;
    } 
    sort(e+1,e+m+1,cmp2);
    if(K<=10){dfs(1);puts("no solution");return 0;} 
    while(1){
        pre();
        if(tot!=n-1) work();
        if(tot==n-1){print();return 0;}
        if(++cct==20) break;
    }
    puts("no solution");
//    cnt=ans[0];ans[0]=0;
//    for(int i=1;i<=ans[0];i++) printf("%d %d %d\n",e[ans[i]].u,e[ans[i]].v,e[ans[i]].w);
    /*for(int i=1;i<=cnt;i++) z[i]=e[ans[i]];
    sort(z+1,z+cnt+1,cmp2);
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1,tot=0,x,y;i<=cnt;i++){
        x=find(z[i].u);y=find(z[i].v);
        if(x!=y){
            fa[y]=x;ans[++ans[0]]=i;
            if(++tot==n-1) break;
        }
    }*/
    /*cnt=ans[0];ans[0]=0;
    for(int i=1;i<=cnt;i++) e[i]=z[ans[i]];
    sort(e+1,e+cnt+1,cmp);*/
//    for(int i=1;i<=cnt;i++) printf("%d %d %d\n",e[i].u,e[i].v,e[i].w);
    return 0;
}
代码留念

相关文章: