G - Railway HDU - 3394(点双连通分量)
作者:互联网
There are some locations in a park, and some of them are connected by roads. The park manger needs to build some railways along the roads, and he would like to arrange tourist routes to each circuit. If a railway belongs to more than one tourist routes, there might be clash on it, and if a railway belongs to none tourist route, it doesn’t need to build.
Now we know the plan, and can you tell us how many railways are no need to build and how many railways where clash might happen.
Input
The Input consists of multiple test cases. The first line of each test case contains two integers, n (0 < n <= 10000), m (0 <= m <= 100000), which are the number of locations and the number of the railways. The next m lines, each line contains two integers, u, v (0 <= u, v < n), which means the manger plans to build a railway on the road between u and v.
You can assume that there is no loop and no multiple edges.
The last test case is followed by two zeros on a single line, which means the end of the input.
Output
Output the number of railways that are no need to build, and the number of railways where clash might happen. Please follow the format as the sample.
Sample Input
8 10 0 1 1 2 2 3 3 0 3 4 4 5 5 6 6 7 7 4 5 7 0 0
Sample Output
1 5
题目大意:给出n个点m条边的无向图简单图(无环无重边),每一个环会安排一条旅游路线,如果一条边不属于任何路线(环),就认为是没有必要的;如果一条边属于多条旅游路线,则认为是会冲突的;求出没必要的边和冲突边数
题解:
- 没必要边很简单,就是桥,不属于任何环;冲突边一开始读错题了,以为安排旅游路线的环必须是尽可能大的,结果跑去求边双连通了。其实应该求点双连通
- 至于冲突边,可以发现,如果一个k个点的环,应该有k条边,若超出k条边,则它肯定不止一个环,这样这个环里每条边都是冲突边了(环里的每一条边属于不止一个环)。
- 因此,求出桥的数量,再求出有多少个点双分量的点数小于边数的,把边数相加即可
代码:还是应该加强一下点双和边双的求法以及和割点割边之间的联系
//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
#include<stack>
#include<vector>
#define rep(i,e) for(int i=0;i<(e);++i)
#define rep1(i,e) for(int i=1;i<=(e);++i)
#define repx(i,x,e) for(int i=(x);i<=(e);++i)
#define pii pair<int,int>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
#ifdef LOCAL
template<typename T>
void dbg(T t){
cout<<t<<" "<<endl;
}
template<typename T, typename... Args>
void dbg(T t, Args... args){
cout<<t<<" ";dbg(args...);
}
#else
#define dbg(...)
#endif // local
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int mod = 1e9+7;
const int N = 500+10;
typedef long long ll;
const int maxn = 1e4+10;
const int maxm =1e5+10;
struct node{
int u,v,next;
}edge[maxm*2];
int head[maxn],low[maxn],dfn[maxn],dfn_cnt,bccno[maxn],bcc_cnt;
int cnt,iscut[maxm*2],cut_cnt;
bool vis[maxn];
int bcce[maxn];
stack<pii>S;
vector<int>B[maxn];
void add(int u,int v)
{
edge[++cnt].v = v;
edge[cnt].u = u;
edge[cnt].next = head[u];
head[u] = cnt;
}
void tarjan(int u,int fa)
{
low[u] = dfn[u] = ++dfn_cnt;
for(int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].v;
pii p = MP(u,v);
if(!dfn[v])
{
S.push(p);
tarjan(v,u);
low[u] = min(low[u],low[v]);
if(low[v] > dfn[u])
cut_cnt++;
if(low[v] >= dfn[u])
{
bcc_cnt++;
B[bcc_cnt].clear();
for(;;){
bcce[bcc_cnt]++;
pii tmp = S.top();S.pop();
if(bccno[tmp.X] != bcc_cnt) B[bcc_cnt].PB(tmp.X),bccno[tmp.X] = bcc_cnt;
if(bccno[tmp.Y] != bcc_cnt) B[bcc_cnt].PB(tmp.Y),bccno[tmp.Y] = bcc_cnt;
if(tmp.X == u && tmp.Y == v) break;
}
}
}else if(dfn[v] < dfn[u] && v != fa)
{
S.push(p);
low[u] = min(low[u],dfn[v]);
}
}
}
void work()
{
int n,m,x,y;
while(cin>>n>>m)
{
for(int i = 0; i <= n; i++)
{
head[i] = -1;
low[i] = dfn[i] = bccno[i] = vis[i] = bcce[i] = 0;
}
bcc_cnt = cut_cnt = 0;
cnt = 1;
dfn_cnt = 0;
memset(iscut,0,sizeof(iscut));
if(n == m && n == 0) break;
for(int i = 0; i < m; i++)
{
cin>>x>>y;
add(x,y);
add(y,x);
}
for(int i = 0; i < n; i++)
{
if(!dfn[i])
tarjan(i,-1);
}
cout<<cut_cnt<<" ";
int res = 0;
for(int i = 1; i <= bcc_cnt; i++)
{
if(bcce[i] > B[i].size())
res += bcce[i];
}
cout<<res<<endl;
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
IOS;
work();
return 0;
}
标签:tmp,HDU,点双,int,cnt,3394,dfn,include,define 来源: https://blog.csdn.net/scau_cdx/article/details/89786950