刷题总结——date(ssoj)

题目:

题目背景

SOURCE:NOIP2015-SHY-9

题目描述

小Y和小Z好不容易有机会相见啦,可是邪恶的小H却不想让他们相见。现在有一些城市,城市之间有双向路径相连,有路径相连的城市之间可以互相到达。小H可以任意选择一条路径,然后用他的邪恶力量污染这条路径,使得它不能被通行。虽然小Y和小Z在千辛万苦之后相遇了,但小Y非常害怕。她想让小Z告诉她,他们初始在哪些点对上,小H就可以选择一条路径污染使得他们不能相见。

注意:如果有一对点之间初始的时候就不联通,也是满足条件的,需要输出这对点。这是因为本来不联通,那么删一条边,当然也不联通。

输入格式

第一行两个数字 N 和 M 。N 表示城市数,M 表示路径数。
第二行到第 M+1 行,两个数 a 和 b。其中 1≤a,b≤N ,表示 a 和 b 之间有路径相连。

输出格式

输出一个整数,表示所求点对的数量

样例数据 1

输入  [复制]

2 1 
1 2

输出

1

备注

【样例说明】
点对(1,2)满足不能相见的条件。

【数据范围】
对 30% 的输入数据 :1≤N≤100,1≤M≤200
对 100% 的输入数据 :1≤N≤20000,1≤M≤40000

题解: 

  就是求每个边双连通分量···然后双连通分量内的点肯定是可以相互到达的,因此我们先算出所有的点对··再减去所有双连通分量中的点对数量(都是合法点对)即可···

  另外注意处理重边以及断点的情况······md图论每次都被这两东西坑···

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=2e4+5;
const int M=4e4+5;
int first[N],next[M*2],go[M*2],tot=1;
int n,m,dfn[N],low[N],cnt=0;
int totgroup,size[N];
bool tag[M*2],visit[N];
long long ans=0;
inline int R()
{
  char c;int f=0;
  for(c=getchar();c<'0'||c>'9';c=getchar());
  for(;c<='9'&&c>='0';c=getchar())
    f=(f<<3)+(f<<1)+c-'0';
  return f;
}
inline void comb(int a,int b)
{
  next[++tot]=first[a],first[a]=tot,go[tot]=b;  
  next[++tot]=first[b],first[b]=tot,go[tot]=a;
}
inline void tarjan(int u,int pre)
{
  dfn[u]=low[u]=++cnt;
  for(int e=first[u];e;e=next[e])
  {
    int v=go[e];
    if(!dfn[v])
    {
      tarjan(v,e);low[u]=min(low[u],low[v]);
      if(dfn[u]<low[v])  tag[e]=tag[e^1]=true;
    }
    else 
      if((e^1)!=pre)  low[u]=min(low[u],dfn[v]);
  }
}
inline void dfs(int u,int pre)
{
  size[totgroup]++;visit[u]=true;
  for(int e=first[u];e;e=next[e])
  {
    if(!tag[e]&&(e^1)!=pre&&!visit[go[e]])
    { 
      int v=go[e];dfs(v,e);    
    }
  }
}
int main()
{
  //freopen("a.in","r",stdin);
  n=R(),m=R();int a,b;
  for(int i=1;i<=m;i++)
  {
    a=R(),b=R();
    comb(a,b);
  }
  for(int i=1;i<=n;i++)
     if(!dfn[i])  tarjan(i,-1);
  for(int i=1;i<=n;i++)
  {  
    if(!visit[i])  totgroup++,dfs(i,-1);
  }
  ans=(long long)n*(n-1)/2;
  for(int i=1;i<=totgroup;i++)
    ans-=(long long)size[i]*(size[i]-1)/2;
  cout<<ans<<endl;
  return 0;
}

 

posted @ 2017-10-08 20:37  AseanA  阅读(158)  评论(0编辑  收藏  举报