1. 程式人生 > >【bzoj4484】【jsoi2015】最小表示

【bzoj4484】【jsoi2015】最小表示

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

5 6

1 2

2 3

3 5

4 5

1 5

1 3

Sample Output

2

HINT

 

Source

By 佚名上傳

[ Submit][ Status][ Discuss]

 

題解 :
        cmp函式:不加型別的話本地不會編譯錯誤,(il好像也是);

        刪邊互相之間是無影響的,所以可刪就刪,和順序無關; 
        由於沒有重邊的無環DAG,一條邊可刪即這條邊的u,v有另一種方式到達;
        DAG轉成topsort序列,bitset優化N*M連通性dp
        $O( \frac{NM}{64} + M*logM)$
        //畢姥爺說得對,還是寫一下的好,不然連bitset的空間都不會開(和vector一樣);
        20181031

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<queue>
 6 #include<cmath>
 7 #include<vector>
 8 #include<stack>
 9 #include<map>
10 #include<bitset>
11 #define rg register
12 #define il inline 
13 #define Run(i,l,r) for(int i=l;i<=r;i++)
14 #define Don(i,l,r) for(int i=l;i>=r;i--)
15 #define ll long long
16 #define ld long double
17 #define inf 0x3f3f3f3f
18 using namespace std;
19 const int N=30001 , M=100010;
20 bitset<N>f[N];
21 int n,m,o,hd[N],st[N],id[N],d[N],idx,q[N],t,w;
22 vector<int>g[N];
23 char gc(){
24     static char*p1,*p2,s[1000000];
25     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
26     return(p1==p2)?EOF:*p1++;
27 }
28 int rd(){
29     int x=0; char c=gc();
30     while(c<'0'||c>'9')c=gc();
31     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
32     return x;
33 }
34 il bool cmp(const int &a,const int &b){return id[a]<id[b];}
35 il void topsort(){
36     for(rg int i=1;i<=n;i++)if(!d[i])q[++w]=i;
37     while(t<w){
38         int u=q[++t];
39         st[id[u]=++idx]=u;
40         for(rg int i=0;i<(int)g[u].size();i++){
41             int v=g[u][i];
42             if(!--d[v]){
43                 q[++w]=v;
44             }
45         }
46     }
47 }
48 int main(){
49     freopen("in.in","r",stdin);
50     freopen("out.out","w",stdout);
51     n=rd(); m=rd();
52     for(rg int i=1,u,v;i<=m;i++){
53         u=rd(); v=rd();
54         g[u].push_back(v); 
55         d[v]++;
56     }
57     topsort();
58     for(rg int i=1;i<=n;i++){
59         sort(g[i].begin(),g[i].end(),cmp);
60     }
61     int ans=0;
62     for(rg int i=n;i;i--){
63         int u=st[i];
64         for(rg int j=0;j<(int)g[u].size();j++){
65             int v=g[u][j];
66             if(f[u].test(id[v])){
67                 ans++;
68             }else{
69                 f[u][id[v]]=1;
70                 f[u]|=f[v];
71             }
72         }
73     }
74     cout<<ans<<endl;
75     return 0;
76 }//by tkys_Austin;
View Code