[NOIPのシミュレーションテスト]:スター・トレック(オイラーの道)

トピックポータル(内部問題4)


入力形式

最初の二つの整数のラインN、M、および惑星のワームホールの数を表します。
双方向直結ワームホールの存在を示す二つの整数、U、Vの次のm行、uおよびv。
各ワームホールを複数回説明します。


出力フォーマット

未使用の経路の自然数を表す整数を裏打ち。


サンプル

サンプル入力

5 4
1 2
1 3
1 4
1 5

サンプル出力

6


データ範囲とヒント

サンプルは説明:
本質的に異なる経路6:
2-1-3-1-4-1-5
2-1-3-4-5-1-4
2-1-4-1-5-1- 3
3-1-2-1-5-1-4
3-1-2-1-4-1-5
4-1-2-1-3-1-5
注意2-1-4-1-3別の-1-5ない本質的に異なる経路は、第一の経路は、本質的に同じです。

制限と規則:
データの10%、$ N、Mの\のleqslant 5つの場合 $。
データの20%、$ nは、m個の\ leqslant 10個のための $。
データの40%、$ N、Mの\のleqslant 100個の場合 $。
データの60%、$ N、Mの\のleqslant 1000 $。
すべてのデータ、$ 1 \ leqslant N、Mのための\ leqslant {10} ^ 5,1 \ leqslant U、Vの\ leqslant n個の$。


問題の解決策

両側にすべての分割は、疑問が残りはオイラー路や図オイラー回路であるように、二つの側面を削除することになります。

これは、3つのケースに分けられます。

  二つのリングから1削除:-2度の2つの点を有する二つのリングからの削除は、オイラーは、このような点は、$ $ SUM、プログラム番号$ C_ {和を持っていると仮定すること} ^ 2 $。

  2.片側の削除とループバック:ループバック穿刺-1の2度のエッジ点を削除し、エッジの削除を検討、上述した二つの奇数ドットは、オイラー経路として、となりますプログラム番号$ C_ {和} ^ 2 \回(M-和)$。

  3.削除双方が共通点を有する:-2度のポイントを、他の2点の度合いがそれぞれオイラー路としての-1両側に接続され、プログラム番号の$ \和\ limits_ {i = 1} ^ nはC_ {D [I]} ^ 2 $。

プログラムの総数である:$ C_ {和} ^ 2 + C_ {和} ^ 2 \回(M-和)+ \和\ limits_ {i = 1} ^ nはC_ {D [I]} ^ 2 $ 。

計算プロセスについては、明らかに上記の計算方法では、我々はいくつかのアイデアの計算の変換を検討し、便利ではありません。

第一のループからケース1とケース2とアップは、残りの辺と組み合わせることができる、プログラム番号M-1、中高校教科書加算の数の差に応じて自己ループ寄与番号m-2の第2の実施形態式利用可能な番号のスキーム:$ \ FRAC {(2 \回M-和-1)\回和} {2} $。

プログラムナンバー3はケースである:掃気しながら$ \ FRAC {\和の\ limits_ {i = 1} ^ ND [I] \回(D [I] -1)} {2} $を得ることができます。

図ではない通信のように決定することを注意していない点が接続されていないが、エッジが通信していない、との差が判定プログラム番号を使用して設定することができる0ユニコムありません。


コードの時間

#include<bits/stdc++.h>
using namespace std;
int n,m;
int rd_geq[100001],rd_leq[100001],f[100001];
long long ans,sum;
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void connect(int x,int y){f[find(x)]=find(y);}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		rd_leq[x]++;//所有的度
		rd_leq[y]++;
		if(x==y)sum++;//统计自环
		else
		{
			rd_geq[x]++;//非自环的度
			rd_geq[y]++;
			connect(x,y);
		}
	}
	int flag=0;
	for(int i=1;i<=n;i++)
		if(rd_leq[i])
		{
			flag=i;
			break;
		}
	for(int i=1;i<=n;i++)
	{
		if(rd_leq[i]&&find(i)!=f[flag])
		{
			puts("0");
			return 0;
		}
		ans+=1LL*(rd_geq[i]-1)*rd_geq[i]/2;//第3种情况
	}
	ans+=sum*(m-sum)+sum*(sum-1)/2;//第1种和第2种情况
	printf("%lld",ans);
	return 0;
}

rp++

おすすめ

転載: www.cnblogs.com/wzc521/p/11222447.html