hdu4781Assignment For Princess2013成都现场赛

来源:互联网 发布:北京互联网地税局软件 编辑:程序博客网 时间:2024/05/16 15:40

题意是:n个点m条边,一个点能到达任意一个点,有向图,没有重边和自环,每条边的权值分别是1到m,没有任何两条边的权值相同,到从一个点出发回到这个点的权值和必须是3的倍数,现需要把这个图输出来,是个构造题,这题我刚开始想的时候看的样例,发现只要是能把3的倍数单拿出来,然后外圈连对3取余1和2的数,里面是3的倍数应该就可以了,可是后来发现边的权值只能是1到m,这样的话,里面的可能3的倍数的数不够用,所以就只能外圈先连成n个点,n条边的图,从1到n的权值分别是1到n-1,n连1的时候得看此时这个圈的权值和加上即将的这条边可能是n,n+1或者是n+2之后对3取余谁得0,然后就初步的构成了一个n个点,n条边的圆环把,那么剩下的m-n条边又应该如何处理呢,刚开始以为是无向图的时候发现怎么连都不对,后来发现是有向图之后茅塞顿开,具体怎么操作呢,当g【u】【v】和没连入图的边的权值k对3取余相同时,就可以把这条边连在u到v之间,不过前提是之前没有u到v或者v到u直接相连的边,那个g数组怎么得到的呢,floyd啊,之后就一切都迎刃而解了,不过这个题我又犯了特别低级的错误,一直在wa,就是a数组应该比m更大,我当成了比n更大,结果cnt加爆了,这个要注意

#include <iostream>#include <string.h>#include <algorithm>using namespace std;const int INF=0x3f3f3f3f;long long T,n,m;long long g[105][105];bool vis[105][105];bool flag[105*105];struct sa{    int u;    int v;    int w;} a[105*105];int cmp(const sa &a,const sa &b)//这块排序可有可无{    if(a.u==b.u)        return a.v<b.v;    return a.u<b.u;}int main(){    ios::sync_with_stdio(false);    int cases=1;    cin>>T;    while(T--)    {        long long sum=0;        memset(a,0,sizeof(a));        memset(g,0,sizeof(g));        memset(vis,0,sizeof(vis));        memset(flag,0,sizeof(flag));        cin>>n>>m;        for(int i=1; i<=n; i++)        {            for(int j=1; j<=n; j++)            {                if(i==j)                {                    g[i][j]=0;                    vis[i][j]=1;                }                else g[i][j]=INF;            }        }        cout<<"Case #"<<cases++<<":"<<endl;        if(m>(n*(n-1)/2))        {            cout<<-1<<endl;            continue;        }        for(int i=1; i<n; i++)        {            a[i].u=i;            a[i].v=i+1;            a[i].w=i;            g[i][i+1]=i;            vis[a[i].u][a[i].v]=1;            flag[i]=1;            sum+=i;        }        a[n].u=n;        a[n].v=1;        if((sum+n)%3==0)        {            a[n].w=n;            g[n][1]=n;            vis[n][1]=1;            flag[n]=1;        }        else if((sum+n+1)%3==0)        {            a[n].w=n+1;            g[n][1]=n+1;            vis[n][1]=1;            flag[n+1]=1;        }        else if((sum+n+2)%3==0)        {            a[n].w=n+2;            g[n][1]=n+2;            vis[n][1]=1;            flag[n+2]=1;        }        for(int k=1; k<=n; k++)        {            for(int i=1; i<=n; i++)            {                for(int j=1; j<=n; j++)                {                    if(g[i][k]+g[k][j]<g[i][j])                        g[i][j]=g[i][k]+g[k][j];                }            }        }        long long cnt=n;        int ans=0;        for(int k=1; k<=m; k++)        {            for(int i=1; i<=n; i++)            {                for(int j=1; j<=n; j++)                {                    if(!flag[k])                    {                        //cout<<++ans<<endl;                        //cout<<k<<endl;                        if((k%3)==(g[i][j]%3)&&!vis[i][j]&&!vis[j][i])                        {                            //cout<<-100<<endl;                            vis[i][j]=1;                            // vis[j][i]=1;                            flag[k]=1;                            a[++cnt].u=i;                            a[cnt].v=j;                            a[cnt].w=k;                            //cout<<cnt<<endl;                        }                    }                }            }        }        bool num=0;        for(int i=1; i<=m; i++)        {            if(!flag[i])            {                num=1;                break;            }        }        if(num)        {            cout<<-1<<endl;            continue;        }        //sort(a+1,a+cnt+1,cmp);        for(int i=1; i<=cnt; i++)        {            cout<<a[i].u<<" ";            cout<<a[i].v<<" ";            cout<<a[i].w<<endl;        }    }    return 0;}
0 0