HDU 4781(图上的构造)

来源:互联网 发布:最新十字绣软件 编辑:程序博客网 时间:2024/06/05 23:02

本题的两个条件:

首先,构造一个图,共有m条边,边权为1 - m互不相同。

图上任意两点间最多有一条有向边,

其次,任意一点经过任意路径回到该点的权值和对3取余为0。

分析:

首先构造一个n个边的有向环,1->2->3...->n->1 ,前n-1条边的权值为1->(n-1),而第n条边为(n,n+1,或者n+2)使得sum%3=0;

那么,这个有向环是符合题意的,只是一些边权为特定值的边还未添加,那么只需在图上找到 dis(i,j)%3 == x%3,那么便可以添加。

#include <cstring>#include <algorithm>#include <cstdio>#include <iostream>#include <cmath>#include <vector>#include <queue>using namespace std;#define rep(i,n) for(int i=0;i<int(n);i++)#define rep1(i,x,y) for(int i=x;i<=(int)y;i++)typedef long long ll;const int N = 85;int n,m,vis[N][N],val[N][N],ans[N][N],hav[N*N];int cal(int x){   rep1(i,1,n)rep1(j,1,n)if(i!=j){       if(vis[i][j] || vis[j][i] ) continue;       if(val[i][j] % 3 == x % 3){           ans[i][j]=x;           hav[x] = 1;           vis[i][j]=1;           return 1;       }   }   return 0;}struct node{   int to,v;   node(int to=0,int v=0):to(to),v(v){}};vector<node> G[N];int dis(int s,int t,int fa,int now){   if(s == t) return now;   rep(i,G[s].size())if(G[s][i].to!=fa){        return dis(G[s][i].to,t,s,now+G[s][i].v);   }}int init(){   for(int i=1;i<=n;i++) G[i].clear();   memset(vis,0,sizeof(vis));   memset(hav,0,sizeof(hav));   int sum = 0;   for(int i=1;i<=n-1;i++){      int x = i, y=i+1;      vis[x][y] = 1;      ans[x][y] = i;      G[x].push_back(node(y,i));      sum+=i;      hav[i]=1;   }   for(int i=n;i<=m;i++){       if((sum+i)% 3== 0){           hav[i] = 1;           vis[n][1] = 1;           ans[n][1] = i;           G[n].push_back(node(1,i));           break;       }   }   for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)      if(i!=j) val[i][j] = dis(i,j,-1,0);   for(int i=1;i<=m;i++)if(!hav[i]){       if(!cal(i)) return 0;   }   return 1;}int main(){    int T,kase=1;    scanf("%d",&T);    while(T--){       scanf("%d %d",&n,&m);       printf("Case #%d:\n",kase++);       if(init()){           rep1(i,1,n) rep1(j,1,n){               if(vis[i][j]) {                   printf("%d %d %d\n",i,j,ans[i][j]);               }           }       }       else printf("-1\n");    }    return 0;}

 

0 0
原创粉丝点击