Codeforces Round #407 (Div. 1):B

来源:互联网 发布:数据修复图片 编辑:程序博客网 时间:2024/06/06 11:36

B. Weird journey
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Little boy Igor wants to become a traveller. At first, he decided to visit all the cities of his motherland — Uzhlyandia.

It is widely known that Uzhlyandia has n cities connected with m bidirectional roads. Also, there are no two roads in the country that connect the same pair of cities, but roads starting and ending in the same city can exist. Igor wants to plan his journey beforehand. Boy thinks a path is good if the path goes over m - 2 roads twice, and over the other 2 exactly once. The good path can start and finish in any city of Uzhlyandia.

Now he wants to know how many different good paths are in Uzhlyandia. Two paths are considered different if the sets of roads the paths goes over exactly once differ. Help Igor — calculate the number of good paths.

Input

The first line contains two integers nm (1 ≤ n, m ≤ 106) — the number of cities and roads in Uzhlyandia, respectively.

Each of the next m lines contains two integers u and v (1 ≤ u, v ≤ n) that mean that there is road between cities u and v.

It is guaranteed that no road will be given in the input twice. That also means that for every city there is no more than one road that connects the city to itself.

Output

Print out the only integer — the number of good paths in Uzhlyandia.

Examples
input
5 41 21 31 41 5
output
6
input
5 31 22 34 5
output
0
input
2 21 11 2
output
1
Note

In first sample test case the good paths are:

  • 2 → 1 → 3 → 1 → 4 → 1 → 5,
  • 2 → 1 → 3 → 1 → 5 → 1 → 4,
  • 2 → 1 → 4 → 1 → 5 → 1 → 3,
  • 3 → 1 → 2 → 1 → 4 → 1 → 5,
  • 3 → 1 → 2 → 1 → 5 → 1 → 4,
  • 4 → 1 → 2 → 1 → 3 → 1 → 5.

There are good paths that are same with displayed above, because the sets of roads they pass over once are same:

  • 2 → 1 → 4 → 1 → 3 → 1 → 5,
  • 2 → 1 → 5 → 1 → 3 → 1 → 4,
  • 2 → 1 → 5 → 1 → 4 → 1 → 3,
  • 3 → 1 → 4 → 1 → 2 → 1 → 5,
  • 3 → 1 → 5 → 1 → 2 → 1 → 4,
  • 4 → 1 → 3 → 1 → 2 → 1 → 5,
  • and all the paths in the other direction.

Thus, the answer is 6.

In the second test case, Igor simply can not walk by all the roads.

In the third case, Igor walks once over every road.


题意:一个无向图,n个点,m条边,询问走遍所有的边且m-2条经过两次,2条经过一次的路径条数。

(这道题是div1的,虽然实际上这题是不难的,但是就是做不出来,很少接触这种图类题目,这是一个原因,同时就是对于欧拉回路欧拉通路不是很熟悉,做该题前还以为是多么高大上的东西,做完后回想起离散学过。好吧,先讲下欧拉回路和通路)

欧拉回路:从一点出发,经过所有的边有且仅有一次然后回到起点的通路就叫欧拉回路。

欧拉通路:从一点出发,经过所有的边有且仅有一次的通路就叫欧拉通路。

欧拉回路的判定:首先必须满足是连通的,然后所有点的度数必须为偶数。

欧拉通路的判定:同样是连通,然后度数为奇数的点为2个或者0个。

该题题解:经过所有的边,这是提示来的,很明显和欧拉路是很像的。想想,如果把所有的边都复制一条出来,那么要满足上述条件,就只需要删掉两条边,然后跑一下欧拉路,看是否存在就是了。那么就可以枚举所有的边,易得删除该边,除该边连接的两个点外的点的度数都为偶数。分两种情况,如果该边是一条自环,那么删除该边后所有的点的度数都是偶数,则删除任意一条边都可以,即ans+=m-1;如果该边不是一条自环,则必须删除与该边连接的点相邻的边,即ans+=g[a].size()-1+g[b].size()-1,同时还要加上自环的个数,因为此时删除自环是成立的。

代码:

//Wud#include <iostream>#include <algorithm>#include <cstdio>#include <stack>#include <cstring>#include <vector>#include <bitset>#include <string>#include <cmath>#include <set>#include <map>#include <queue>using namespace std;typedef long long ll;const int maxn = 1e6+7;const int INF = 0x3f3f3f3f;vector<int> g[maxn];//图bool vis[maxn];//是否可达int n,m;struct edge{int a,b;}s[maxn];//边int in[maxn];//度数int loop;//自环个数void dfs(int u){    vis[u] = 1;    for(int i = 0;i < g[u].size();i++){        int v = g[u][i];        if(!vis[v]) dfs(v);    }}//连通图判断int main(){    while (scanf("%d %d",&n,&m)!=EOF){        loop = 0;        for(int i = 1;i <= n;i++) g[i].clear();        memset(vis,0,sizeof(vis));        for(int i = 0;i < m;i++){            int a,b;            scanf("%d %d",&a,&b);            s[i].a = a,s[i].b = b;            if(a!=b){                g[a].push_back(b);                g[b].push_back(a);            }            else loop++;            in[a]++,in[b]++;        }        ll ans = 0;        for(int i = 1;i <= n;i++){            if(in[i]!=0){                dfs(i);                break;            }        }        int l = 0;        for(int i = 1;i <= n;i++){            if(!vis[i]&&in[i]!=0){                cout<<0<<endl;                l = 1;                break;            }        }        if(l) continue;        for(int i = 0;i < m;i++){            int a = s[i].a;            int b = s[i].b;            if(a!=b){                ans+=(g[a].size()-1+g[b].size()-1+loop);            }            else{                ans+=m-1;            }        }        cout<<ans/2<<endl;    }    return 0;}
开动脑子,多思考。

0 0
原创粉丝点击