构造法 说的高大上点就是构造法,我感觉就是要什么搞什么~~~
题意:输入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]);
}
}
}
}
}