[JSOI2015]最小表示

题目大意:
尽可能多地去掉一个有向无环图上的边,使得图的连通性不变。

思路:
拓扑排序,然后倒序求出每个结点到出度为$0$的点的距离$d$,再倒序遍历每一个点$x$,以$d$为关键字对其出边降序排序,尝试加入每一条边,若加边之前两点已经连通,则说明这条边可以删去。可以用bitset维护图的连通性,注意原图是有向图,因此不能用并查集维护。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #include<bitset>
 6 #include<algorithm>
 7 #include<functional>
 8 inline int getint() {
 9     char ch;
10     while(!isdigit(ch=getchar()));
11     int x=ch^'0';
12     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
13     return x;
14 }
15 const int V=30001;
16 std::vector<int> e[V];
17 inline void add_edge(const int u,const int v) {
18     e[u].push_back(v);
19 }
20 int n;
21 int in[V]={0},top[V]={0};
22 inline void Kahn() {
23     std::queue<int> q;
24     for(int i=1;i<=n;i++) {
25         if(!in[i]) q.push(i);
26     }
27     int cnt=0;
28     while(!q.empty()) {
29         int x=q.front();
30         q.pop();
31         top[x]=++cnt;
32         for(unsigned i=0;i<e[x].size();i++) {
33             int &y=e[x][i];
34             if(!--in[y]) {
35                 q.push(y);
36             }
37         }
38     }
39 }
40 struct Vertex {
41     int top,id;
42     bool operator > (const Vertex &another) const {
43         return top>another.top;
44     }
45 };
46 Vertex v[V];
47 int dis[V]={0};
48 int ans=0;
49 inline bool cmp(const int x,const int y) {
50     return dis[x]>dis[y];
51 }
52 inline void DP() {
53     for(int i=0;i<n;i++) {
54         v[i]=(Vertex){top[i+1],i+1};
55     }
56     std::sort(&v[0],&v[n],std::greater<Vertex>());
57     for(int i=0;i<n;i++) {
58         int &x=v[i].id;
59         for(unsigned j=0;j<e[x].size();j++) {
60             int &y=e[x][j];
61             dis[x]=std::max(dis[x],dis[y]+1);
62         }
63     }
64 }
65 std::bitset<V> bit[V];
66 inline void cut() {
67     for(int i=0;i<n;i++) {
68         int &x=v[i].id;
69         bit[x].set(x);
70         std::sort(e[x].begin(),e[x].end(),cmp);
71         for(unsigned j=0;j<e[x].size();j++) {
72             int &y=e[x][j];
73             if(bit[x][y]) ans++;
74             bit[x]|=bit[y];
75         }
76     }
77 }
78 int main() {
79     n=getint();
80     for(int m=getint();m;m--) {
81         int u=getint(),v=getint();
82         add_edge(u,v);
83         in[v]++;
84     }
85     Kahn();
86     DP();
87     cut();
88     printf("%d\n",ans);
89     return 0;
90 }

 

posted @ 2017-08-21 12:48  skylee03  阅读(139)  评论(0编辑  收藏  举报