hdu4781构造法

构造法 说的高大上点就是构造法,我感觉就是要什么搞什么~~~安静

题意:输入n,m,要你构造一个有向图,要求每两个点之间只有一条边,任意两边只有一条有向边,不能有自环,从每个点出发都能到达其他点,

都能回到自己,每个环的权值%3==0,边权 权值为 (1-m)严格递增。

思路:先构造1-n 这n-1条边,边权为[1,n-1],然后在构造边(n,1)如果n%3==1的话那(n,1)这条边的边权,为n+2,否则为n

题目说了m>=n+3,所以是满足的,这里就构造了n条边,并且满足题目的性质了。

那么剩下m-n条边,我们构造的话假如这条边权值为w 只需要满足~~~i点到 j点的距离dis[i][j]%3==w%3那么我们就将其连一条边,就算构造成功了。

代码;

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define inf 0x3f3f3f3f
int n,m;
int map1[100][100];
int dis[100][100];
int vis[100*100*100];
int vis1[100][100];
void fod()
{  for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(dis[i][k]!=inf&&dis[k][j]!=inf&&dis[i][j]>dis[i][k]+dis[k][j])
            {
                dis[i][j]=dis[i][k]+dis[k][j];
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    int cas=1;
    while(t--)
    {
        scanf("%d %d",&n,&m);
        memset(map1,inf,sizeof(map1));
        memset(vis1,0,sizeof(vis1));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<n;i++)
        {
            map1[i][i+1]=i;
            vis[i]=1;
            vis1[i][i+1]=1;
            vis1[i+1][i]=1;
        }
        if(n%3==1) map1[n][1]=n+2,vis[n+2]=1;
        else map1[n][1]=n,vis[n]=1;
        vis1[1][n]=1;
        vis1[n][1]=1;
        memcpy(dis,map1,sizeof(dis));
        fod();
        int k=n;
        for(;k<=m;k++)
        {
            if(vis[k]) continue;
            int flag=1;
            for(int i=1;i<=n&&flag;i++)
            {
                for(int j=1;j<=n&&flag;j++)
                {
                    if(i!=j&&map1[i][j]!=inf||vis1[i][j]) continue;

                    if(dis[i][j]%3==k%3)  {
                            map1[i][j]=k;
                            flag=0;
                            vis1[i][j]=1,
                            vis1[j][i]=1;
                    }
                }
            }
            if(flag) {printf("Case #%d:\n",cas++); printf("-1\n"); break;}
        }
        if(k>m)
      {

        printf("Case #%d:\n",cas++);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(map1[i][j]!=inf) printf("%d %d %d\n",i,j,map1[i][j]);
            }
        }
        }

    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值