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

  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. GFS分布式文件系统环境部署与管理

    Gluster分布式文件系统 准备环境五台虚拟机 创建/gfs目录,把软件包全部拷贝目录 把yum仓库的源放进bak下才能执行以下脚本 并指定主机名这四台机器都要执行脚本 [root@localhos ...

  2. DFS-BFS深度优选遍历和广度优先遍历

    https://www.jianshu.com/p/b086986969e6 DFS--需要借助stack实现 stack.push stack.pop BFS--需要借助队列queue stack- ...

  3. [luogu4799 CEOI2015 Day2] 世界冰球锦标赛(折半搜索)

    传送门 Solution 折半搜索裸题,注意\(long long\) Code #include <cmath> #include <cstdio> #include < ...

  4. Java 实现邮件发送功能

    1.新建model SendMail.java import java.util.Properties; public class SendMail { // 发送邮件的服务器的IP和端口 priva ...

  5. NOIP 2016 换教室(期望dp)

    第一次做期望dp 并不知道每个阶段的期望之和就是整个的期望之和 所以一直卡在这 期望=代价*概率 然后注意只有申请了才算期望,否则按原来的. 这道题和前几个课程,申请的限制,当前选或不选,有关 这样很 ...

  6. Codeforces 879A/B

    A. Borya's Diagnosis 传送门:http://codeforces.com/contest/879/problem/A 本题是一个模拟问题. 依次访问n个元素,第i个元素首次出现于s ...

  7. NET 爬虫

    最近经常听说或者接触关于网络爬虫的问题,只是一直看到被人写的代码.而没有真正的做过实践, 昨天做了一下尝试,其中采用网络流行的扩展类库 http://html-agility-pack.net/?z= ...

  8. Netty学习总结(3)——Netty百万级推送服务

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  9. python进行excel操作

    使用模块 xlsxwriter : http://xlsxwriter.readthedocs.io/ 可以自定义表格合并.样式 加各种2D图表 写入格式化表格数据时,与pandas结合速度更快!

  10. [bzoj2938][Poi2000]病毒_AC自动机

    病毒 bzoj-2938 Poi-2000 题目大意:给你n个01串,问是否存在一个无限长的01串使得这个01的任意子串都不等于给出的01串. 注释:All_length<=30,000 想法: ...