NYOJ 925 国王的烦恼

来源:互联网 发布:淘宝卖饰品利润怎么样 编辑:程序博客网 时间:2024/04/29 10:26

并查集的一道题目,不知道为何有些博客上说成是最小生成树,也许最小生成树也可以解决这个问题,坎坎坷坷打完了代码,上交就TLE,好菜啊,不过看了看自己的方法复杂度确实够高的。
看了网上的代码,一个很好的想法:反向考虑,,路断变路修,,,同一天的算一个。。一句就解决了我的超时问题,当然对并查集也有一些改变的,,我觉得自己写不出来。。
首先附自己的代码,虽然TLE,但是很好的帮助我理解了这个题目的解法。。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m;int pa[100010];struct Node{    int a,b,num;}p[100010];void init()     //初始化   该函数可以根据具体情况保存和初始化需要的内容{    for(int i=1;i<=n;i++)    {        pa[i]=i;    }}int findset(int a)  //不带路劲压缩{    while(pa[a]!=a)    {        a = pa[a];    }    return a;}void union_nodes(int a, int b)      //集合合并{    int a1=findset(a);    int b1=findset(b);    if(a1!=b1)        //这个判定条件可选,主要是为了防止findset路径压缩的时候出现死循环    {        pa[a1]=b1;        //如果存的是有向图,并且做题时集合中元素的顺序很重要,不能忽略,那么这里应该用"pa[a] = b;"    }}int main(){    int maxn,i,j,k,ans,change;    while(~scanf("%d %d",&n,&m))    {        maxn=0,ans=0;        init();        for(i=0;i<m;i++)        {            scanf("%d %d %d",&p[i].a,&p[i].b,&p[i].num);            union_nodes(p[i].a,p[i].b);            maxn=max(maxn,p[i].num);        }        int anss=0;        //printf("%d\n",maxn);        for(i=0;i<=maxn;i++)        {            init();            change=ans;            ans=0;            for(j=0;j<n;j++)            {                p[j].num-=1;                if(p[j].num>0)                    union_nodes(p[j].a,p[j].b);            }            for(k=1;k<=n;k++)            {                if(pa[k]==k)                    ans++;            }            if(ans>change&&i!=0)                anss++;        }        printf("%d\n",anss);    }    return 0;}

附别人的代码及链接

#include<stdio.h>  #include<string.h>  #include<stdlib.h>  #include<iostream>  #include<algorithm>using namespace std;int pre[100010],a[100010];struct road{int x,y,d;bool operator <(const road& e)const/设立优先级{return d>e.d;}}s[100010];void lol(int n){    int i;    for(i=0;i<=n;i++)//i的数量一定要大于等于n,否则wrong        pre[i]=i;}int find(int x)//寻根{    if(x==pre[x])    return pre[x];    return pre[x]=find(pre[x]);}bool ok(int x,int y)//连接检测{    int fx=find(x);    int fy=find(y);    if(fx==fy)    return false;    pre[fy]=fx;    return true;//这里改得好}int main(){    int n,m;    int i;    while(scanf("%d%d",&n,&m)!=EOF)    {        lol(n);        for(i=0;i<m;i++)        scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].d);        sort(s,s+m);//排序        int num=0,day=-1;        for(i=0;i<m;i++)        {           bool bz=ok(s[i].x,s[i].y);            if(bz&&day!=s[i].d)//反向考虑,,路断变路修,,,同一天的算一个。。            {                num++;                day=s[i].d;            }        }          printf("%d\n",num);    }    return 0;}        
0 0
原创粉丝点击