codeforces C. Restore Graph

题意:构造一个有n个顶点,每个点度不超过k,然后给出每一个点到达一个定点的最短距离d数组,然后构造出这样的一个图;

思路:排序之后,有两个距离为0的或者没有直接输出-1,然后用两个游动下表,后面的与前面的度都小于k且它们的距离相差1,就建1条边。然后dfs输出就可以。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cmath>
 6 #include <vector>
 7 #define maxn 100010
 8 using namespace std;
 9
10 int n,k;
11 int d[maxn];
12 int du[maxn];
13 struct node
14 {
15     int x,id;
16     bool operator <(const node &a)const
17     {
18         return x<a.x;
19     }
20 } p[maxn];
21 vector<int>g[maxn];
22
23 void dfs(int x)
24 {
25     for(int i=0; i<(int)g[x].size(); i++)
26     {
27         printf("%d %d\n",x,g[x][i]);
28         dfs(g[x][i]);
29     }
30 }
31
32 int main()
33 {
34     scanf("%d%d",&n,&k);
35     for(int i=1; i<=n; i++)
36     {
37         scanf("%d",&d[i]);
38         p[i].x=d[i];
39         p[i].id=i;
40     }
41     sort(p+1,p+n+1);
42     if(p[1].x==0&&p[2].x==0||p[1].x!=0)
43     {
44         printf("-1\n");
45         return 0;
46     }
47     int l=1,r=2;
48     int cnt=0;
49     bool flag=false;
50     while(r<=n)
51     {
52         if(p[r].x==p[l].x)
53         {
54             printf("-1\n");
55             return 0;
56         }
57         if(p[r].x-p[l].x==1&&du[p[l].id]<k&&du[p[r].id]<k)
58         {
59             g[p[l].id].push_back(p[r].id);
60             cnt++;
61             du[p[l].id]++;
62             du[p[r].id]++;
63             r++;
64         }
65         else if(p[r].x-p[l].x>1||du[p[l].id]>=k)
66         {
67             l++;
68             if(l==r)
69             {
70                 flag=true;
71                 break;
72             }
73         }
74         else if(du[p[r].id]>=k)
75         {
76             r++;
77         }
78         else
79         {
80             r++;
81         }
82     }
83     if(flag)
84     {
85         printf("-1\n");
86         return 0;
87     }
88     printf("%d\n",cnt);
89     dfs(p[1].id);
90     return 0;
91 }

时间: 2024-08-30 02:59:37

codeforces C. Restore Graph的相关文章

CodeForces 404C Restore Graph (构造)

题意:让人构造一个图,满足每个结点边的数目不超过 k,然后给出每个结点到某个结点的最短距离. 析:很容易看出来如果可能的话,树是一定满足条件的,只要从头开始构造这棵树就好,中途超了int...找了好久. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include

CodeForces 21D Traveling Graph 状压dp+欧拉回路

题目链接:点击打开链接 题意: 给定n个点m条边的无向图 求从1点开始经过每条边至少一次最后回到1点的最小路程 显然就是找一条路径可重复的欧拉回路 思路: 首先对于欧拉回路的结论是:所有点的度数都为偶数 因为所有边至少经过一次,那么可以把题意转换成加最少多少条边使得图满足以上结论 而加的边目的是为了把奇度数转成偶度数,先floyd一下得到任意点间加边的最小花费 dp[i]表示状态i下度数都为偶数的最小花费. 状压dp,把i状态下,所有未选择的点中挑2个奇度数的转移即可. #include <cs

Codeforces 466E Information Graph(dfs+并查集)

题目链接:Codeforces 466E Information Graph 题目大意:一开始有n个员工,他们互相独立.现在有三种操作. 1 u v,v称为u的上级 2 u,从u发起一份文件,逐层递交给上级 3 u v,询问u是否查阅过v号文件. 解题思路:将每个文件移动的范围处理出来,然后对于每次询问,将询问拆成两个标记,假设查询x是否浏览过第k号文件,第k号文件的范围为u-v,那么在最后dfs时,遍历到x,判断是否经过u:遍历到v时,判断是否经过x.如果两个都满足,则是YES. #inclu

Codeforces 464B Restore Cube(暴力)

题目链接:Codeforces 464B Restore Cube 题目大意:给定8个点坐标,对于每个点来说,可以随意交换x,y,z坐标的数值.问说8个点是否可以组成立方体. 解题思路:直接暴力枚举即可,保证一个点的坐标不变,枚举量为67,将上一层判断. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef

【Codeforces 404C】Restore Graph

[链接] 我是链接,点我呀:) [题意] 每个节点的度数不超过k 让你重构一个图 使得这个图满足 从某个点开始到其他点的最短路满足输入的要求 [题解] 把点按照dep的值分类 显然只能由dep到dep+1连边 设cnt[dep]表示到起点的距离为dep的点的集合 如果cnt[dep].size>cnt[dep+1].size 那么只要把dep层的前cnt[dep+1].size个点和dep+1层的点连就好了 否则 只能让dep层的点每个多连几个dep+1层的点了 [代码] import java

Codeforces 165D Beard Graph 边权树剖+树状数组

Beard Graph 题意:给你一颗由n个结点组成的树,支持以下操作:1 i:将第i条边染成黑色(保证此时该边是白色),2 i:将第i条边染成白色(保证此时该边是黑色),3 a b:找出a,b两点之间只由黑边组成的最短路径. 思路:树链剖分+树状数组,把每条边的权值放到它指向的点中去,初始全为黑边,黑边权值为1,白边权值为-inf,黑边变白边,将点权增加-inf,白边变黑边点权增加inf,因为不可能白边边白边,所以可以这样做,查询的时候要减去2个点的最近公共祖先的点权,最近公共祖先可通过树剖的

CodeForces - 986C AND Graph

不难想到,x有边连出的一定是 (2^n-1) ^ x 的一个子集,直接连子集复杂度是爆炸的...但是我们可以一个1一个1的消去,最后变成补集的一个子集. 但是必须当且仅当 至少有一个 a 等于 x 的时候, 可以直接dfs(all ^ x) ,否则直接消1连边... Discription You are given a set of size mm with integer elements between 00 and 2n?12n?1 inclusive. Let's build an u

【CodeForces 624C】Graph and String

题 题意 n个表示abc三个字符的点,a和b是相连的,b和c是相连的,相同的是相连的,现在给你n个点和他们之间的m条边,判断是否存在这样的字符串,存在则给出一个符合条件的. 分析 我的做法是找出所有的b,因为b是只和自己没有连接,所以有n-1个连线,然后找出第一个不是b的,然后所有和该点没有连线的都设置为c,有连线而不是b的就设置为a,然后再把该点设置为a. 接下来,根据题目条件,判断一下我设置出来的字符串成不成立.就是如果不相连接却是相同字母或者有b字母,还有如果相连接却是a和c,那都是不符合

CodeForces 466E Information Graph --树形转线性+并查集

题意:有三种操作: 1.新增一条边从y连向x,此前x没有父节点 2.x接到一份文件,(文件标号逐次递增),然后将这份文件一路上溯,让所有上溯的节点都接到这份文件 3.查询某个节点x是否接到过文件F 解法: 首先要知道一个性质,节点u在v的上溯路径上的话要满足: L[u]<=L[v] && R[u] >= R[v] (先进后出) 先将所有的边都读入,dfs得出L[u],R[u],然后将查询分为tot类(tot=总文件种数),记录每一类有那些地方查询了,然后如果type=2,那么记