HDU3861 (强连通缩点+二分匹配最小路径覆盖)
2015-08-27 18:51
344 查看
题意:把城市至少分成几个块,规则有三
1. A能B,B能到A,那么A,B一定要在一起。
2. 一个城市只能属于一个块。
3. 在一个块里的城市,任意2点之间必须有路径。
对于规则1,就是说强连通的必须在一起,所以用Tarjan进行缩点,然后,规则2,3就是求DAG最小路径覆盖。(最小路径覆盖=顶点数-最大匹配)
1. A能B,B能到A,那么A,B一定要在一起。
2. 一个城市只能属于一个块。
3. 在一个块里的城市,任意2点之间必须有路径。
对于规则1,就是说强连通的必须在一起,所以用Tarjan进行缩点,然后,规则2,3就是求DAG最小路径覆盖。(最小路径覆盖=顶点数-最大匹配)
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<set> #include<map> #include<string> #include<cstring> #include<stack> #include<queue> #include<vector> #include<cstdlib> #define lson (rt<<1),L,M #define rson (rt<<1|1),M+1,R #define M ((L+R)>>1) #define cl(a,b) memset(a,b,sizeof(a)); #define LL long long #define P pair<int,int> #define X first #define Y second #define pb push_back #define fread(zcc) freopen(zcc,"r",stdin) #define fwrite(zcc) freopen(zcc,"w",stdout) using namespace std; const int maxn=50005; const int inf=999999; vector<int> G[maxn];//原图 vector<int> G2[maxn];//缩点后,二分匹配的图 struct Tarjan{ int low[maxn],dfn[maxn],s[maxn],belong[maxn]; bool ins[maxn]; int num,cnt,top; void dfs(int u){ dfn[u]=low[u]=++num; s[top++]=u; ins[u]=true; int N=G[u].size(); for(int i=0;i<N;i++){ int v=G[u][i]; if(!dfn[v]){ dfs(v); low[u]=min(low[u],low[v]); } else if(ins[v]&&dfn[v]<low[u]){ low[u]=dfn[v]; } } if(low[u]==dfn[u]){ int v=-1; cnt++; while(u!=v){ v=s[--top]; ins[v]=false; belong[v]=cnt; } } } void solve(int n){ cl(ins,false); cl(belong,0); cl(dfn,0); cnt=num=top=0;///不要忘记 for(int i=1;i<=n;i++){ if(!dfn[i])dfs(i); } } }tarjan; struct Xiong{ int matching[maxn]; bool vis[maxn]; bool dfs(int u){ int N=G2[u].size(); for(int i=0;i<N;i++){ int v=G2[u][i]; if(vis[v])continue; vis[v]=true; if(matching[v]==-1||dfs(matching[v])){ matching[v]=u; return true; } } return false; } int hungar(int Nx){ cl(matching,-1); int ans=0; for(int i=1;i<=Nx;i++){ cl(vis,false); if(dfs(i))ans++; } return ans; } }xiong; int main(){ int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d%d",&n,&m); for(int i=0;i<=n;i++){ G[i].clear(); G2[i].clear(); } for(int i=0;i<m;i++){ int x,y; scanf("%d%d",&x,&y); G[x].pb(y); } tarjan.solve(n); for(int i=1;i<=n;i++){//缩点 for(int j=0;j<G[i].size();j++){ if(tarjan.belong[i]!=tarjan.belong[G[i][j]]){ G2[tarjan.belong[i]].pb(tarjan.belong[G[i][j]]); } } } int ans=xiong.hungar(tarjan.cnt); printf("%d\n",tarjan.cnt-ans); //printf("tarjan.cnt = %d, ans = %d\n",tarjan.cnt,ans); } return 0; }
相关文章推荐
- Myeclipse 10,删除工程导致 severUI打不开
- PM提高效率的工具
- git push用法和常见问题分析
- Linux学习日记--基础命令(7)--bash中的变量,配置文件
- “调试器的协议与调试对象不兼容”错误的解决
- HBase Java客户端编程
- hdu 1069 Monkey and Banana(动态规划)
- 深入Java类加载器
- “调试器的协议与调试对象不兼容”错误的解决
- 08-25 convertView、ViewHolder、MyfruitPractice、divider、Header
- PHP中isset、empty、is_null实验测试
- 正则表达式与python中re模块
- 教育的意义
- HDU 5378(Leader in Tree Land-利用概率dp)
- MDT 2013 UPDATE 1正式版安装实战系列预告
- 常见编码格式
- 坚持不下去了,就看看
- 08-21 RadioGroup,RadioButton autoLink属性 TextView中ellipsize属性 TextView的属性
- 08-24 CheckBox、ImageView、ArrayAdapter、SimpleAdapter、自定义Adapter
- Android中Toast的使用