hdu 4781 /构造 出 符合要求的图

哎,第一次见给点数和边数,让按要求还原出有向图的。

要求概况一下:

1.强连通。

2.任意俩点直接之间只有一条有向边,自己和自己无边。

3.任意一个闭合回路权和%3为0。

4.每条边的权理论不同,而且是1,2,3..m

开始就想到必有一个大环1->2->3->.....n,n->1;  模拟比赛时.,没有往下想了。。

先添加边: i->i+1是权为I,之后从(n,n+1,n+2)中选一条添加N到1的权,使得闭环%3=0.

之后处理 剩下m-n条边,

:注意若 在 i--->j 附加边,则有w(i,j)%3==从i到j边权之和%3即可(容易证明)

枚举每条即可(n<80,m<n*n/7)。

#include<iostream>
#include<cstring>
using namespace std;
int n,m;
int mark[6400];
int vis[85][85];
int main()
{
    int T;
    cin>>T;int ct=1;
    while(T--)
    {
        for(int i=0;i<=m;i++)
            mark[i]=0;
        memset(vis,0,sizeof(vis));
           cin>>n>>m;
        for(int i=1;i<n;i++)
        {
           // cout<<i<<" "<<i+1<<" "<<i<<endl;
            mark[i]=1;vis[i][i+1]=vis[i+1][i]=i;
        }
        int tei=0;
        for(int i=n;i<n+3;i++)
           if((n*(n-1)/2+i)%3==0)
           {
              //cout<<n<<" "<<1<<" "<<i<<endl;
              tei=i;
              mark[i]=1;
              vis[n][1]=vis[1][n]=i;
              break;
          }
       for(int i=n;i<=m;i++)
       {
           if(!mark[i])
           {
               int flags=0;
               for(int j=1;j<=n;j++)
               {

                for(int k=j+2;k<=n;k++)
                {

                    if(!vis[j][k]&&((k-j)*(j+k-1)/2)%3==i%3)
                    {
                        vis[j][k]=vis[k][j]=i;
                        mark[i]=1;
                        flags=1;
                        break;
                    }
                }
                if(flags)break;
               }
           }
       }
       bool flag=1;
       for(int i=1;i<=m;i++)
       {
           if(mark[i]==0)
             {
                 flag=0;break;
             }
       }
       cout<<"Case #"<<ct++<<":"<<endl;
       if(flag==0)
       cout<<-1<<endl;
       else
       {
           for(int i=1;i<=n;i++)
             for(int j=(i+1);j<=n;j++)
             {
                 if(vis[i][j]!=0&&!(i==1&&j==n))
                 {
                     cout<<i<<" "<<j<<" "<<vis[i][j]<<endl;
                 }
             }
            cout<<n<<" "<<1<<" "<<tei<<endl;
       }
    }
}
时间: 2024-10-05 20:38:44

hdu 4781 /构造 出 符合要求的图的相关文章

hdu 3879 hdu 3917 构造最大权闭合图 俩经典题

hdu3879  base station : 各一个无向图,点的权是负的,边的权是正的.自己建一个子图,使得获利最大. 一看,就感觉按最大密度子图的构想:选了边那么连接的俩端点必需选,于是就以边做点,轻轻松松构造了最大权闭合图.简单题.分分钟搞定. hdu3917 :road  constructions :这题题目看了半天没理解...感觉描述的不好...一个有向图,每条路有响应公司承保,若选了该公司,那么该公司的路必需全部选,还有,该公司的承保的路的下面的一条路对应公司也要选,求最大获利.构

hdu 4781 Assignment For Princess(构造法)

Assignment For Princess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 958    Accepted Submission(s): 286 Special Judge Problem Description Long long ago, in the Kingdom Far Far Away, there li

HDU 4888 Redraw Beautiful Drawings 网络流 建图

题意: 给定n, m, k 下面n个整数 a[n] 下面m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵,若有多解输出Not Unique,若无解输出Impossible 思路:网络流,,, n行当成n个点,m列当成m个点 从行-列连一条流量为k的边,然后源点-行连一条a[i]的边, 列-汇点 流量为b[i] 瞎了,该退役了 T^T #include<stdio.h> #include<string.h> #include<iostream&

HDU - 6150 构造题

最近的vj好垃圾,老崩,实名吐槽 HDU - 6150 题意:给出一个错误的求最小点覆盖的函数,需要来构造一组样例,使得那个函数跑出来的答案是正解的3倍以上. 很巧妙的构造技巧,首先想法就是弄一个二分图,让正确答案是上面的n个点,我们需要构造的就是下面的点,这就不知道为什么要这样构造了.也就是分块的思想. 从1~n每次分n/i个块,每个块的大小为i,对于每个块下面就构造出一个点跟块里所有点相连. 这样下面的点就是n+n/2+n/3+n/4+...大约就是nlnn个点,那我们要求nlnn>=3n,

hdu 5444(构造二叉树然后遍历)

Elven Postman Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1286    Accepted Submission(s): 731 Problem Description Elves are very peculiar creatures. As we all know, they can live for a ver

hdu 4289 利用最大流思想求图的最小割

http://acm.hdu.edu.cn/showproblem.php?pid=4289 Problem Description You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to anothe

编程之美 找出符合条件的整数

好不容易把内容看懂~ 最主要的一句话:只需要将10k%N的结果与余数信息数组里非空的元素相加,再去模N,看看会不会出现新的余数~ 时间太紧迫~先把自己写的代码贴上,以后再详解 1 int FindMin(int N) 2 { 3 if(N <= 1) 4 return N; 5 6 int* A = new int[N];//这个是记录模N余i之后的数值 7 8 memset(A, -1, sizeof(int) * N); 9 int factor = 1; 10 A[1] = 1; 11 1

Java:根据前序遍历与中序遍历构造出一个二叉树

给你前序遍历中序遍历,如何构造出一个二叉树? 思路: 1. 明确前序遍历与中序遍历的顺序 前序遍历:根→左子树→右子树 中序遍历:左子树→根→右子树 2. 根据前序遍历可确认根节点,在中序遍历中根节点是一个分水岭,可由根节点分辨出左右子树 3. 对左右子树分别重复第2步,可以找出左右子树的子树,也就是递归操作 代码: public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x;

hdu 4781 Beautiful Soup 构造

并不是很难的一个构造,我在比赛的时候把题目读错了,补题的时候想得比较粗糙,迟迟没过这题,之后想法慢慢细致起来,还是将这题过了. #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0