AtCoder Regular Contest 102 - D All Your Paths are Different Lengths (构造 二进制)

版权声明:是自己手打的没错 https://blog.csdn.net/Mr_Treeeee/article/details/82319811

https://arc102.contest.atcoder.jp/tasks/arc102_b

题意:

给你一个L,让你构造一张图,点数不超过20,边数不超过60。可以重边。

他的拓扑排序必须为1 2 3…… n,即边只能从小连到大。

这张图必须确切存在L条不同的边,长度分别为0,1,2,3……L-1.

L=<1e6

POINT:

如果L是1,2,4,8,16这种整二进制数,很好办。只要给i到i+1连上0和1<<(i-1)的两条边就可以。

问题出在把这个整二进制数处理完了之后,后面还有1怎么办。比如101101_{2}这个数(45)。

最前面的32很好办。就按照之前的方法可以构造完0到31。剩下来的1,4,8个数。

分别是(32),(33,34,35,36),(37,38,39,40,41,42,43)

这时候,加一条边i到n,长度为x,则会增加x,x+1,……,x+2^(i-1)-1那么多边。

所以 加 1-n 长度为32,   3-n 长度为33,   4-n长度为37。这三条边。

至于32,33,37这三个长度是怎么算的,看规律便能知晓。

#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
struct node
{
	int u,v,w;
};

node a[70];
int cnt=0;
void add(int u,int v,int w)
{
	cnt++;
	a[cnt].u=u;a[cnt].v=v;a[cnt].w=w;
}
int main()
{

	int L;
	scanf("%d",&L);
	int tmp=L;
	int n=0;
	while(tmp){
		n++;
		tmp>>=1;
	}
	for(int i=1;i<n;i++){
		add(i,i+1,1<<(i-1));
		add(i,i+1,0);
	}
	int w=1<<(n-1),k=1;;
	while(L!=1){
		if(L&1) {
			add(k,n,w);
			w|=1<<(k-1);
		}
		k++;
		L>>=1;
	}
	printf("%d %d\n",n,cnt);
	for(int i=1;i<=cnt;i++){
		printf("%d %d %d\n",a[i].u,a[i].v,a[i].w);
	}


	return 0;
}

猜你喜欢

转载自blog.csdn.net/Mr_Treeeee/article/details/82319811
今日推荐