Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 432 Solved: 223
[Submit][Status][Discuss]
Description
【故事背景】
还记得去年JYY所研究的强连通分量的问题吗?去年的题目里,JYY研究了对于有向图的“加边”问题。对于图论有着强烈兴趣的JYY,今年又琢磨起了“删边”的问题。
【问题描述】
对于一个N个点(每个点从1到N编号),M条边的有向图,JYY发现,如果从图中删去一些边,那么原图的连通性会发生改变;而也有一些边,删去之后图的连通性并不会发生改变。
JYY想知道,如果想要使得原图任意两点的连通性保持不变,我们最多能删掉多少条边呢?
为了简化一下大家的工作量,这次JYY保证他给定的有向图一定是一个有向无环图(JYY:大家经过去年的问题,都知道对于给任意有向图的问题,最后都能转化为有向无环图上的问题,所以今年JYY就干脆简化一下大家的工作)。
Input
输入一行包含两个正整数N和M。
接下来M行,每行包含两个1到N之间的正整数x_i和y_i,表示图中存在一条从x_i到y_i的有向边。
输入数据保证,任意两点间只会有至多一条边存在。
N<=30,000,M<=100,000
Output
输出一行包含一个整数,表示JYY最多可以删掉的边数。
Sample Input
1 2
2 3
3 5
4 5
1 5
1 3
Sample Output
HINT
Source
题解 :
cmp函数:不加类型的话本地不会编译错误,(il好像也是);
删边互相之间是无影响的,所以可删就删,和顺序无关;
由于没有重边的无环DAG,一条边可删即这条边的u,v有另一种方式到达;
DAG转成topsort序列,bitset优化N*M连通性dp
$O( \frac{NM}{64} + M*logM)$
//毕姥爷说得对,还是写一下的好,不然连bitset的空间都不会开(和vector一样);
20181031
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
#include<bitset>
#define rg register
#define il inline
#define Run(i,l,r) for(int i=l;i<=r;i++)
#define Don(i,l,r) for(int i=l;i>=r;i--)
#define ll long long
#define ld long double
#define inf 0x3f3f3f3f
using namespace std;
const int N= , M=;
bitset<N>f[N];
int n,m,o,hd[N],st[N],id[N],d[N],idx,q[N],t,w;
vector<int>g[N];
char gc(){
static char*p1,*p2,s[];
if(p1==p2)p2=(p1=s)+fread(s,,,stdin);
return(p1==p2)?EOF:*p1++;
}
int rd(){
int x=; char c=gc();
while(c<''||c>'')c=gc();
while(c>=''&&c<='')x=(x<<)+(x<<)+c-'',c=gc();
return x;
}
il bool cmp(const int &a,const int &b){return id[a]<id[b];}
il void topsort(){
for(rg int i=;i<=n;i++)if(!d[i])q[++w]=i;
while(t<w){
int u=q[++t];
st[id[u]=++idx]=u;
for(rg int i=;i<(int)g[u].size();i++){
int v=g[u][i];
if(!--d[v]){
q[++w]=v;
}
}
}
}
int main(){
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
n=rd(); m=rd();
for(rg int i=,u,v;i<=m;i++){
u=rd(); v=rd();
g[u].push_back(v);
d[v]++;
}
topsort();
for(rg int i=;i<=n;i++){
sort(g[i].begin(),g[i].end(),cmp);
}
int ans=;
for(rg int i=n;i;i--){
int u=st[i];
for(rg int j=;j<(int)g[u].size();j++){
int v=g[u][j];
if(f[u].test(id[v])){
ans++;
}else{
f[u][id[v]]=;
f[u]|=f[v];
}
}
}
cout<<ans<<endl;
return ;
}//by tkys_Austin;