对多校赛的题目,我深感无力。题目看不懂,英语是能懂的,题目具体的要求以及需要怎么做没有头绪。样例怎么来的都不明白。好吧,看题解吧。

  http://www.cnblogs.com/kane0526/archive/2013/07/21/3203992.html

题目大意:

  把一幅有向图中的点最少可以划分为几个区域。划分的规则是:1、可以互相到达的点必须在同一区域。2、每个城市都必须被划分。3、对于属于同一区域中的任意两点,要么满足u->v,要么满足v->u。

  第三条规则需要着重解释一下。对于测试数据1->2,1->3,因为2与3之间没有边,所以2与3必须被划为2个区域。所以答案是2。

做法:

  建图求强连通(Tarjan算法),然后对得到的DAG,重新建图。遍历每条边,不属于同一连通分支的点就连一条边。正向图和反向图都可以。

  最后答案就是SCC - ans。SCC 是连通分支数,ans是最大匹配数。因为这里求的最小路径覆盖。

  最小路径覆盖 =  顶点数 -  最大匹配数

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int N =, M=,INF=0x3f3f3f3f;;
struct node
{
int to, next;
}edge[M];
int head[N], low[N], dfn[N], sta[N], belg[N], num[N];
bool vis[N];
int scc,index,top, tot;
void tarbfs(int u)
{
int i,j,k,v;
low[u]=dfn[u]=++index;
sta[top++]=u;
vis[u]=;
for(i=head[u];i!=-;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarbfs(v);
if(low[u]>low[v]) low[u]=low[v];
}
else if(vis[v]&&low[u]>dfn[v]) low[u]=dfn[v];
}
if(dfn[u]==low[u])
{
scc++;
do
{
v=sta[--top];
vis[v]=;
belg[v]=scc;
num[scc]++;
}
while(v!=u) ;
}
}
void Tarjan(int n)
{
memset(vis,,sizeof(vis));
memset(dfn,,sizeof(dfn));
memset(num,,sizeof(num));
memset(low,,sizeof(low));
index=scc=top=;
for(int i=;i<=n;i++)
if(!dfn[i]) tarbfs(i);
}
void init()
{
tot=;
memset(head,-,sizeof(head));
}
void addedge(int i,int j)
{
edge[tot].to=j; edge[tot].next=head[i];head[i]=tot++;
}
int cx[N],cy[N],dx[N],dy[N];
bool bmask[N];
int nx,dis,ans;
vector<int> bmap[N];
bool searchpath()
{
queue<int> q;
dis=INF;
memset(dx,-,sizeof(dx));
memset(dy,-,sizeof(dy));
for(int i=;i<=nx;i++)
{
if(cx[i]==-){ q.push(i); dx[i]=; }
while(!q.empty())
{
int u=q.front(); q.pop();
if(dx[u]>dis) break;
for(int i=;i<bmap[u].size();i++)
{
int v=bmap[u][i];
if(dy[v]==-)
{
dy[v]= dx[u] + ;
if(cy[v]==-) dis=dy[v];
else
{
dx[cy[v]]= dy[v]+;
q.push(cy[v]);
}
}
}
}
}
return dis!=INF;
}
int findpath(int u)
{
for(int i=;i<bmap[u].size();i++)
{
int v=bmap[u][i];
if(!bmask[v]&&dy[v]==dx[u]+)
{
bmask[v]=;
if(cy[v]!=-&&dy[v]==dis) continue;
if(cy[v]==-||findpath(cy[v]))
{
cy[v]=u; cx[u]=v;
return ;
}
}
}
return ;
}
void maxmatch()
{
ans=;
memset(cx,-,sizeof(cx));
memset(cy,-,sizeof(cy));
while(searchpath())
{
memset(bmask,,sizeof(bmask));
for(int i=;i<=nx;i++)
if(cx[i]==-) ans+=findpath(i);
}
}
int main()
{
//freopen("test.txt","r",stdin);
int cas,i,j,k,n,m;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
init();
while(m--)
{
scanf("%d%d",&i,&j);
addedge(i,j);
}
Tarjan(n);
for(i=;i<=n;i++) bmap[i].clear();
for(i=;i<=n;i++)
{
for(k=head[i];k!=-;k=edge[k].next)
{
j=edge[k].to;
if(belg[i]!=belg[j]) bmap[belg[j]].push_back(belg[i]);
}
}
nx=scc;
maxmatch();
printf("%d\n",scc-ans);
}
return ;
}

hdu3861 The King’s Problem 强连通缩点+DAG最小路径覆盖的更多相关文章

  1. HDU 3861 The King’s Problem (强连通缩点+DAG最小路径覆盖)

    <题目链接> 题目大意: 一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.所有点只能属于一块区域:2,如果两点相互可达,则这两点必然要属于同一区域:3,区域内任意两点 ...

  2. 【HDU3861 强连通分量缩点+二分图最小路径覆盖】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意:一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.有边u到v以及有 ...

  3. Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

    题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 ...

  4. Light OJ 1406 Assassin`s Creed 减少国家DP+支撑点甚至通缩+最小路径覆盖

    标题来源:problem=1406">Light OJ 1406 Assassin`s Creed 意甲冠军:向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路: ...

  5. hdoj 3861 The King’s Problem【强连通缩点建图&&最小路径覆盖】

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  6. HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/ar ...

  7. HDU 3861 The King's Problem(强连通分量缩点+最小路径覆盖)

    http://acm.hdu.edu.cn/showproblem.php?pid=3861 题意: 国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意 ...

  8. hdu 3861 The King’s Problem trajan缩点+二分图匹配

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  9. hdu3861 强连通分量缩点+二分图最最小路径覆盖

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

随机推荐

  1. MySQL基础命令小结

    数据库授权登录[root@localhost ~]# mysql -uroot -p123456mysql> grant select,lock tables on auth.* to 'adm ...

  2. jsp+servlet 导出Excel表格

    1.项目的目录结构 2.创建一个用户类,下面会通过查询数据库把数据封装成用户实例列表 package csh.entity; /** * @author 悦文 * @create 2018-10-24 ...

  3. appium滑动

    在app应用日常使用过程中,会经常用到在屏幕滑动操作.如刷朋友圈上下滑操作.浏览图片左右滑动操作等.在自动化脚本该如何实现这些操作呢? 在Appium中模拟用户滑动操作需要使用swipe方法,该方法定 ...

  4. 【剑指Offer】1、二维数组中的查找

      题目描述:   在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否 ...

  5. 15.5.2 【Task实现细节】骨架方法的结构

    尽管骨架方法中的代码非常简单,但它暗示了状态机的职责.代码清单15-11生成的骨架方 法如下所示: [DebuggerStepThrough] [AsyncStateMachine(typeof(De ...

  6. Linux放弃到入门

    流星,因为短暂而美丽,划过黑寂的夜空,释放出那一闪而逝的光芒,虽然微弱,但却没有人能无视它的存在.人生如同流星,充满了精彩与传奇,如同一支美丽的传说,究竟能否想流星那样短暂,别人决定不了,上天也决定不 ...

  7. java的几种对象(PO,VO,DAO,BO,POJO)解释 (转)

    java的几种对象(PO,VO,DAO,BO,POJO)解释 一.PO:persistant object 持久对象,可以看成是与数据库中的表相映射的java对象.最简单的PO就是对应数据库中某个表中 ...

  8. hdu 4858 容器的简单模拟

    我用临接表模拟容器超时 #include<stdio.h> #include<string.h> #include<vector> using namespace ...

  9. 如何用arcgis进行WGS84的投影坐标变换

    转自原文 如何用arcgis进行WGS84的投影坐标变换 通常情况下,要求WGS 84下的投影坐标,选择UTM投影. 1.UTM投影 UTM投影全称为“通用横轴墨卡托投影”UNIVERSAL TRAN ...

  10. Android Studio Mac 快捷键整理分享

    代码高亮 OSX:Shift + Cmd + F7 Win/Linux:Alt + J 代码高亮向上查找 OSX:Shift + Cmd + G Win/Linux:Shift + F3 代码高亮向下 ...