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 lived many little animals. And you are the beloved princess who is marrying the prince of a rich neighboring kingdom. The prince, who turns out to be a handsome guy, offered you a golden engagement ring that
can run computer programs!

  The wedding will be held next summer because your father, the king, wants you to finish your university first.

  But you did’t even have a clue on your graduation project. Your terrible project was to construct a map for your kingdom. Your mother, the queen, wanted to make sure that you could graduate in time.

  Or your wedding would have to be delayed to the next winter. So she told you how your ancestors built the kingdom which is called the Roads Principle:

  1. Your kingdom consists of N castles and M directed roads.

  2. There is at most one road between a pair of castles.

  3. There won’t be any roads that start at one castle and lead to the same one.

  She hoped those may be helpful to your project. Then you asked your cousin Coach Pang (Yes, he is your troubling cousin, he always asks you to solve all kinds of problems even you are a princess.), the Minister of Traffic, about the castles and roads. Your
cousin, sadly, doesn’t have a map of the kingdom. Though he said the technology isn’t well developed and it depends on your generation to contribute to the map, he told you the Travelers Guide, the way travelers describe the amazing road system:

  1. No matter which castle you start with, you can arrive at any other castles.

  2. Traveling on theM roads will take 1, 2, 3, ... ,M days respectively, no two roads need the same number of days.

  3. You can take a round trip starting at any castle, visiting a sequence of castles, perhaps visiting some castles or traveling on some roads more than once, and finish your journey where you started.

  4. The total amount of days spent on any round trip will be a multiple of three.

  But after a month, you still couldn’t make any progress. So your brother, the future king, asked your university to assign you a simpler project. And here comes the new requirements. Construct a map that satisfies both the Roads Principle and the Travelers
Guide when N and M is given.

  There would probably be several solutions, but your project would be accepted as long as it meets the two requirements.

Now the task is much easier, furthermore your fiance sent two assistants to help you.

  Perhaps they could finish it within 5 hours and you can think of your sweet wedding now.

Input

  The first line contains only one integer T, which indicates the number of test cases.

  For each test case, there is one line containing two integers N, M described above.(10 <= N <= 80, N+3 <= M <= N2/7 )

Output

  For each test case, first output a line “Case #x:”, where x is the case number (starting from 1).

  Then output M lines for each test case. Each line contains three integers A, B, C separated by single space, which denotes a road from castle A to castle B and the road takes C days traveling.

  Oh, one more thing about your project, remember to tell your mighty assistants that if they are certain that no map meets the requirements, print one line containing one integer -1 instead.

  Note that you should not print any trailing spaces.

Sample Input

1
6 8

Sample Output

Case #1:
1 2 1
2 3 2
2 4 3
3 4 4
4 5 5
5 6 7
5 1 6
6 1 8

Hint

The restrictions like N >= 10 will be too big for a sample. So the sample is just a simple case for the detailed formats of input and output,
 and it may be helpful for a better understanding. Anyway it won’t appear in actual test cases.

题意:有一个n个点,m条边的有向图,每条边的权值分别为1,2,3........m,让你构

造满足下列条件的有向图。

1:每两个点之间最多只有一条有向边,且不存在自环。

2:从任意点出发都可以达到其他任意一个点,包括自己。

3:任意一个有向环的权值和都是3的倍数。

思路: 首先我们可以将点1到n连成一条链,边的权值分别是1到n-1,然后点n到点1连

一条边,若n%3为0或2,则边权值为n,否则边权值为n+2(m>=n+3),现在我们构造

出了一个环且满足上述三个条件。那么接下来如何构造剩下的m-n条边呢?

现在我们不管怎么构造都满足第二个条件了,而且现在每个点到自己的距离都是3的倍

数。那么如果我要在u,v两点之间连一条全值为len的边,那么只要满足len%3==dist[u][v]%3即

可(dist表示原环中两个点之间的距离),然后在构造的时候还要注意不要违背第一个条件,所

以我们可以用G[i][j]来表示i,j之间是否右边,如果按这样构造无法构造出图,则无解。

如图 :  要在点2与点4之间加一条权值为 len 的有向边 ,因为

( dist[2][4]+dist[4][2] ) % 3 = 0 , 加的权值为 len 的边要满足

(dist[4][2] + len)% 3 = 0 。有上述两式说明加的边的权值

只要满足len % 3==dist[2][4]%3 (因为是有向边,所以dist[2][4]!=dist[4][2] )。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf=999999999;
const int M=7000;
const int maxn=95;

struct node
{
    int u,v,val;
    node() {}
    node(int _u,int _v,int _val):u(_u),v(_v),val(_val) {}
} a[M];
int dis[maxn][maxn],cnt,n,m;
bool G[maxn][maxn],visited[M];

void initial()
{
    cnt=0;
    memset(G,0,sizeof(G));
    memset(visited,0,sizeof(visited));
    for(int i=0; i<maxn; i++)
        for(int j=0; j<maxn; j++)
        {
            if(i==j)  dis[i][j]=0;
            else dis[i][j]=inf;
        }
}

void input()
{
    scanf("%d %d",&n,&m);
}

void ready()
{
    int t;
    for(int i=1; i<n; i++)
    {
        a[cnt++]=node(i,i+1,i);
        dis[i][i+1]=i;
        G[i][i+1]=1;
        visited[i]=1;
    }
    if(n%3==1)  t=n+2;
    else t=n;
    a[cnt++]=node(n,1,t);
    dis[n][1]=t;
    visited[t]=1;
    G[n][1]=1;
}

void floyd()
{
    for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}

bool judge(int len)
{
    int tmp=len%3;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
        {
             if(i!=j && !G[i][j] && !G[j][i])
             {
                  if(dis[i][j]%3==tmp)
                  {
                       a[cnt++]=node(i,j,len);
                       visited[len]=1;
                       G[i][j]=1;
                       return true;
                  }
             }
        }
    return false;
}

void solve(int co)
{
    floyd();
    printf("Case #%d:\n",co);
    for(int i=1; i<=m; i++)
        if(!visited[i])
            if(!judge(i))
            {
                printf("-1\n");
                return ;
            }
    for(int i=0;i<cnt;i++)  printf("%d %d %d\n",a[i].u,a[i].v,a[i].val);
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int co=1; co<=T; co++)
    {
        initial();
        input();
        ready();
        solve(co);
    }
    return 0;
}

时间: 2024-08-02 14:16:09

hdu 4781 Assignment For Princess(构造法)的相关文章

HDU 4781 Assignment For Princess(YY乱搞)

http://acm.hdu.edu.cn/showproblem.php?pid=4781 Assignment For Princess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 639    Accepted Submission(s): 196 Special Judge Problem Description Long

HDU 5741 Helter Skelter(构造法)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5741 [题目大意] 一个01相间的串,以0开头,给出的序列每个数字表示连续的0的个数或者1的个数,现在有m个询问,求0的个数为a且1的个数为b的串是否存在. [题解] 我们发现形如11001这样子以1为开头结尾的串是包含1001这样子的串的,同理以0为开头结尾的串也是包含了一些开头结尾数字相同的子串. 可以发现,当0的个数固定,1的个数是数轴上的一个区间,而且在0的个数相差1时,必定可以取到相同

hdu4781 Assignment For Princess(构造)

题目链接:hdu4781 Assignment For Princess 题意:n个点m条边,每条有向边的权值分别是1,2,3…m,一个点能到达任意一个点,没有重边和自环,没有任何两条边的权值相同,任意一个有向环的权值和必须是3的倍数,现在需要把这个图输出来. 题解:注意到题目给出的范围m >= n+3,所以一定是可以构造出一个1~n的回路使得权值和为3的倍数的,可以让前n-1条边权值为1~n-1,第n条边(n->1)可以为n, n+1, n+2从而满足题意,后面再连任意两条不相邻的边时,边权

利用子集构造法实现NFA到DFA的转换

概述 NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够比较方便的机械实现且识别能力方面也和NFA相当.本次实验采用子集构造法来实现不带空弧的由NFA到DFA的转换. 子集构造法的算法如下: 设NFA为M=(K,Σ,f,S0,Z),则构造相应的DFA  M′=(Q,Σ,f′,I0,F)①取I0=S0:②对于状态集Q中任一尚未标记的状态qi={Si1,Si

hdu 2609 How many 最小表示法

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1248    Accepted Submission(s): 486 Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100

生成子集 (增量构造法)

使用增量构造法可以构造出升序数组arr的不重复子集,并且按字典序排序 #include<bits/stdc++.h> using namespace std; int arr[16]; inline void print_subset(int *index, int cur, int n)///cur值这里可以理解为在这个堆栈层子集的集合数 { for(int i=0; i<cur; i++) {printf("%d ", arr[index[i]]);} if(cu

HDU 5014 Number Sequence ( 构造 )

HDU 5014 Number Sequence ( 构造 ) 题目意思: 给出一个数列 由0 - n 组成 然后需要构造一个数列 (也是由0-n组成),使得 sum(A[i] ^ B[i])的值最大. 分析: 异或不能出现比这个数大的情况,,所以要从大的数往前找. 现计算出当前判断数的二进制位的位数m,然后再与2^m - 1进行异或,这样会保证最大,具体为什么,自己可以想一想 比如: 5 - 101 -- 3位 - 对应 111 101 ^ 111 = 010 代码: #include <cs

hdu how many prime numbers 筛选法求素数

/* * hdu How many prime numbers * date 2014/5/13 * state AC */ #include <iostream> #include <cmath> #include <cstdio> using namespace std; bool isPrime(int x) { int sqr=sqrt(x*1.0); for(int i=2;i<=sqr;i++) { if(x%i==0)return false; }

hdu 5302 Connect the Graph(构造)

题意:对于一幅无向图,有黑白边连接,连接i条白边的点数为a[0],a[1],a[2],连接i条黑边的点数为b[0],b[1],b[2], a[0]+a[1]+a[2]=b[0]+b[1]+b[2],求该无向图的边数及各边情况; 思路:构造法:若连接边数为1的点为奇数,则该图不存在: 图的总点数为a[0]+a[1]+a[2]; #include<cstdio> #include<cstring> #include<algorithm> using namespace st