首页 > 代码库 > HDU - 3861 The King’s Problem (强连通分量+最小路径覆盖)

HDU - 3861 The King’s Problem (强连通分量+最小路径覆盖)

技术分享

思路:tarjarn缩点,然后剩下的就是纯粹的最小路径覆盖,最小路径覆盖=顶点数-匹配数。匹配数跑一遍匈牙利即可。

技术分享
  1 #include <iostream>
  2 #include <queue>
  3 #include <stack>
  4 #include <cstdio>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <string>
 14 #include <sstream>
 15 #include <time.h>
 16 #define x first
 17 #define y second
 18 #define pb push_back
 19 #define mp make_pair
 20 #define lson l,m,rt*2
 21 #define rson m+1,r,rt*2+1
 22 #define mt(A,B) memset(A,B,sizeof(A))
 23 using namespace std;
 24 typedef long long LL;
 25 //const double PI = acos(-1);
 26 const int N=5e5+10;
 27 const LL mod=1e9+7;
 28 const int inf = 0x3f3f3f3f;
 29 const LL INF=0x3f3f3f3f3f3f3f3fLL;
 30 const int MAXN = 5010;//点数
 31 const int MAXM = 200010;//边数
 32 struct Edge
 33 {
 34     int to,next;
 35 } edge[MAXM],edge1[MAXM];
 36 int head[MAXN],tot;
 37 int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
 38 int Index,top;
 39 int scc;//强连通分量的个数
 40 bool Instack[MAXN];
 41 int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
 42 //num数组不一定需要,结合实际情况
 43 void addedge(int u,int v)
 44 {
 45     edge[tot].to = v;
 46     edge[tot].next = head[u];
 47     head[u] = tot++;
 48 }
 49 void Tarjan(int u)
 50 {
 51     int v;
 52     Low[u] = DFN[u] = ++Index;
 53     Stack[top++] = u;
 54     Instack[u] = true;
 55     for(int i = head[u]; i != -1; i = edge[i].next)
 56     {
 57         v = edge[i].to;
 58         if( !DFN[v] )
 59         {
 60             Tarjan(v);
 61             if( Low[u] > Low[v] )Low[u] = Low[v];
 62         }
 63         else if(Instack[v] && Low[u] > DFN[v])
 64             Low[u] = DFN[v];
 65     }
 66     if(Low[u] == DFN[u])
 67     {
 68         scc++;
 69         do
 70         {
 71             v = Stack[--top];
 72             Instack[v] = false;
 73             Belong[v] = scc;
 74             num[scc]++;
 75         }
 76         while( v != u);
 77     }
 78 }
 79 void solve(int N)
 80 {
 81     memset(DFN,0,sizeof(DFN));
 82     memset(Instack,false,sizeof(Instack));
 83     memset(num,0,sizeof(num));
 84     Index = scc = top = 0;
 85     for(int i = 1; i <= N; i++)
 86         if(!DFN[i])
 87             Tarjan(i);
 88 }
 89 int head1[MAXN],tot1;
 90 void init()
 91 {
 92     tot = 0;
 93     tot1 = 0;
 94     memset(head,-1,sizeof(head));
 95     memset(head1,-1,sizeof(head1));
 96 }
 97 void addedge1(int u,int v)
 98 {
 99     edge1[tot1].to = v;
100     edge1[tot1].next = head1[u];
101     head1[u] = tot1++;
102 }
103 int linker[MAXN];
104 bool used[MAXN];
105 bool dfs(int u)
106 {
107     for(int i = head1[u]; i != -1 ; i = edge1[i].next)
108     {
109         int v = edge1[i].to;
110         if(!used[v])
111         {
112             used[v] = true;
113             if(linker[v] == -1 || dfs(linker[v]))
114             {
115                 linker[v] = u;
116                 return true;
117             }
118         }
119     }
120     return false;
121 }
122 int hungary(int uN)
123 {
124     int res = 0;
125     memset(linker,-1,sizeof(linker));
126     for(int u = 1; u <=uN; u++)
127     {
128         mt(used,0);
129         if(dfs(u))
130         {
131             res++;
132         }
133     }
134     return res;
135 }
136 int main()
137 {
138 #ifdef Local
139     freopen("data.txt","r",stdin);
140 #endif
141     ios::sync_with_stdio(false);
142     cin.tie(0);
143     int T;
144     int n,m,u,v;
145     cin>>T;
146     while(T--)
147     {
148         cin>>n>>m;
149         init();
150         for(int i=0; i<m; i++)
151         {
152             cin>>u>>v;
153             addedge(u,v);
154         }
155         solve(n);
156         for(int i=1; i<=n; i++)
157         {
158             for(int j=head[i]; ~j; j=edge[j].next) //j表示读入的是第几条边
159             {
160                 if(Belong[i]!=Belong[edge[j].to])
161                 {
162                    addedge1(Belong[i],Belong[edge[j].to]);
163                    //cout<<Belong[i]<<"->"<<Belong[edge[j].to]<<endl;
164                 }
165             }
166         }
167         //cout<<hungary(scc)<<endl;
168         cout<<scc-hungary(scc)<<endl;
169     }
170 #ifdef Local
171     cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
172 #endif
173 }
View Code

 

HDU - 3861 The King’s Problem (强连通分量+最小路径覆盖)