標籤:sort 維護 return 排序 const empty function inline type
題目大意:
儘可能多地去掉一個有向非循環圖上的邊,使得圖的連通性不變。
思路:
拓撲排序,然後倒序求出每個結點到出度為$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 }
[JSOI2015]最小表示