Codeforces Round #520 (Div. 2) D. Fun with Integers

链接

http://codeforces.com/contest/1062/problem/D

题解

  • 如果一个图 G G 中的一条路径包含每条边恰好一次,则这条路径成为欧拉路径
  • 如果一个回路是欧拉路径,则该路径成为欧拉回路
  • 包含欧拉回路的图成为欧拉图
  • 无向图 G G 是欧拉图的充要条件:每个顶点的度数都是偶数
  • 有向图 G G 是欧拉图的充要条件:所有顶点的入度等于出度

在这道题目中,把每个数字看作一个点,如果 x x y y 右边,那么 x -x 肯定也和 y y 有边,所以这张无向图每个极大连通子图都是欧拉图
那么这个子图上的答案就是所有边的权值和
对所有的子图统计一下,最后取个 m a x max 就完了

代码

#include <bits/stdc++.h>
#define ll long long
#define cl(x) memset(x,0,sizeof(x))
#define maxn 8000010
using namespace std;
int head[maxn], to[maxn], nex[maxn], w[maxn], tot=1, N;
bool vis[maxn];
ll ans, val, cnt;
void adde(int a, int b, int c){to[++tot]=b;w[tot]=c;nex[tot]=head[a];head[a]=tot;}
void adde2(int a, int b, int c){adde(a,b,c), adde(b,a,c);}
int read(int x=0)
{
	int c, f=1;
	for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
	for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
	return f*x;
}
void init()
{
	int i, j;
	N=read();
	for(i=2;i<=N;i++)for(j=i+i;j<=N;j+=i)adde2(N+i,N+j,j/i), adde2(N+i,N-j,j/i), adde2(N-i,N+j,j/i), adde2(N-i,N-j,j/i);
}
void dfs(int pos)
{
	cnt++;
	for(int &p=head[pos];p;p=nex[p])
		if(!vis[p])vis[p]=vis[p^1]=1, val+=w[p], dfs(to[p]);
}
int main()
{
	int i;
	init();
	for(i=1;i<=N;i++)val=0, dfs(i), ans=max(ans,val);
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/84197241