hdu 3639 有向图缩点+建反向图+搜索
题意:给个有向图,每个人可以投票(可以投很多人,一次一票),但是一个人只能支持一人一次,支持可以传递,自己支持自己不算,被投支持最多的人。
开始想到缩点,然后搜索,问题是有一点想错了!以为支持按票数计算,而不是按人数!还各种树形dp/搜索求可以到达边数。。提交WA了。。。
又反复读了题目之后才发现。。错误。。只要人数就行。。。问题简单了许多。。。
缩点成有向无环图后:每个SCC中支持的人数就是scc里面的人,要求可到达的点最多的点,当然要放过来求方便:反向图那个点可以到达的点最多!于是建反向图直接dfs即可,记录答案有点麻烦。。。提交就A了。。。这题总体花了我2多个小时。。算失败。。。
#include<iostream>
#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxv=5005,maxe=50005;
int nume=0;int head[maxv];int e[maxe][3];
void inline adde(int i,int j,int c)
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
e[nume++][2]=c;
}
int dfn[maxv];int low[maxv];int vis[maxv];int ins[maxv]; stack<int>sta;
int scc[maxv];int numb=0;int times=0;
int n,m; int sccsize[maxv];
void tarjan(int u)
{
dfn[u]=low[u]=times++;
ins[u]=1;
sta.push(u);
for(int i=head[u];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(!vis[v])
{
vis[v]=1;
tarjan(v);
if(low[v]<low[u])low[u]=low[v];
}
else if(ins[v]&&dfn[v]<low[u])
{
low[u]=dfn[v];
}
}
if(low[u]==dfn[u])
{
numb++;int counted=0;
int cur;
do
{
cur=sta.top();
sta.pop();
ins[cur]=0;
scc[cur]=numb;
counted++;
}while(cur!=u);
sccsize[numb]=counted;
}
}
struct pi
{
int id;
int w;
};
bool my (pi a,pi b)
{
if(a.w!=b.w)
return a.w>b.w;
else
return a.id<b.id;
}
int sums=0;
vector<vector<int> >e2(maxv+1);
int ind[maxv];
void dfs(int u)
{
for(int i=0;i<e2[u].size();i++)
{
int v=e2[u][i];
if(!vis[v])
{
vis[v]=1;
sums+=sccsize[v];
dfs(v);
}
}
}
vector<int>sumss;
void solve()
{
for(int i=0;i<n;i++)
{
if(!vis[i])
{
vis[i]=1;
tarjan(i);
}
}
for(int i=0;i<n;i++)
for(int j=head[i];j!=-1;j=e[j][1])
{
int v=e[j][0];
if(scc[i]!=scc[v])
{
e2[scc[v]].push_back(scc[i]);
ind[scc[i]]++;
}
}
int minsums=0;
vector<pi>ans;
for(int i=1;i<=numb;i++)
{
sums=0;
memset(vis,0,sizeof(vis));
if(ind[i]==0)
{
vis[i]=1;
sums+=sccsize[i]-1;
dfs(i);
if(sums>=minsums)
{
pi tp;
tp.w=sums;
tp.id=i;
ans.push_back(tp);
minsums=sums;
}
}
}
vector<int>realans;
for(int i=0;i<ans.size();i++)
{
if(ans[i].w==minsums)
{
realans.push_back(ans[i].id);
}
}
for(int j=0;j<realans.size();j++)
for(int i=0;i<n;i++)
{
if(scc[i]==realans[j])
{
sumss.push_back(i);
}
}
sort(sumss.begin(),sumss.end());
printf("%d\n",minsums);
for(int i=0;i<sumss.size();i++)
{
if(i!=sumss.size()-1)
printf("%d ",sumss[i]);
else
printf("%d\n",sumss[i]);
}
}
void read_build()
{
int aa,bb,cc;
for(int i=0;i<m;i++)
{
scanf("%d%d",&aa,&bb);
adde(aa,bb,0);
}
}
void init()
{
numb=times=nume=0;
sumss.clear();
for(int i=0;i<maxv;i++)
{
head[i]=-1;
ins[i]=dfn[i]=low[i]=scc[i]=vis[i]=0;
sccsize[i]=0;
ind[i]=0;
e2[i].clear();
}
}
int main()
{
int T;
scanf("%d",&T);
int ct=1;
while(T--)
{
scanf("%d%d",&n,&m);
init();
read_build();
printf("Case %d: ",ct++);
solve();
}
return 0;
}
hdu 3639 有向图缩点+建反向图+搜索的更多相关文章
- hdu 3072 有向图缩点成最小树形图计算最小权
题意,从0点出发,遍历所有点,遍历边时候要付出代价,在一个SCC中的边不要付费.求最小费用. 有向图缩点(无需建立新图,,n<=50000,建则超时),遍历边,若不在一个SCC中,用一个数组更新 ...
- hdu 1827 有向图缩点看度数
题意:给一个有向图,选最少的点(同时最小价值),从这些点出发可以遍历所有. 思路:先有向图缩点,成有向树,找入度为0的点即可. 下面给出有向图缩点方法: 用一个数组SCC记录即可,重新编号,1.... ...
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013480600/article/details/32140501 HDU 3639 Hawk-a ...
- HDU 4635 (完全图 和 有向图缩点)
题目链接:HDU 4635 题目大意: 给你一个有向图,加有向边,使得这个图是简单有向图.问你最多加多少条有向边. 简单有向图: 1.不存在有向重边. 2.不存在图循环.(注意是不存在 “图” 循环 ...
- HDU 1045 Fire Net(行列匹配变形+缩点建图)
题意:n*n的棋盘上放置房子.同一方同一列不能有两个,除非他们之间被墙隔开,这种话. 把原始图分别按行和列缩点 建图:横竖分区.先看每一列.同一列相连的空地同一时候看成一个点,显然这种区域不可以同一时 ...
- HDU 3639 Hawk-and-Chicken(良好的沟通)
HDU 3639 Hawk-and-Chicken 题目链接 题意:就是在一个有向图上,满足传递关系,比方a->b, b->c,那么c能够得到2的支持,问得到支持最大的是谁,而且输出这些人 ...
- 对Tarjan——有向图缩点算法的理解
开始学tarjan的时候,有关无向图的割点.桥.点双边双缩点都比较容易地理解了,唯独对有向图的缩点操作不甚明了.通过对luoguP2656_采蘑菇一题的解决,大致搞清了tarjan算法的正确性. 首先 ...
- hdu 4778 Gems Fight! 博弈+状态dp+搜索
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4102743.html 题目链接:hdu 4778 Gems Fight! 博弈+状态dp+搜 ...
- hdoj 3861 The King’s Problem【强连通缩点建图&&最小路径覆盖】
The King’s Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
随机推荐
- CodeForces 651B
#include <cstdio> #include <algorithm> using namespace std; int a[1005], n, temp, maxk; ...
- Vue之简易的留言板功能
今天我将带大家通过Vue的todolist案例来完成一个简易的网页留言板! LES'T GO! 首先我们需要在页面上搭建一个input文本输入框,并设置提交按钮,通过循环指令来完成输入框的信息提交! ...
- Crane UVA - 1611 思路+构造
题目:题目链接 思路:思路+构造,假设 i 在pos 位置,那么如果 (pos-i-1)*2+i+1 <= n,那么可以操作一次换过来,如果他们之间元素个数是偶数,那么交换 i - pos,如 ...
- 第5模块闯关CSS练习题
1.列举你知道的css选择器? 说道css选择器,大家都知道有许多种,但是真要你去掰着手指头数一数的话,你可能需要数几分钟.其实这么多选择器,完全可以分为两类: 标签选择器(*是特殊情况),可但标签, ...
- js 监听后退事件及跳转页面
//直接跳转 window.location.href="b.html"; //返回上一级页面 window.history.back(-1); //返回下一级页面 window. ...
- mysql查询当天的数据
mysql查询当天的数据 贴代码: #两个时间都使用to_days()函数 select * from reple where to_days(create_time) = to_days(NOW() ...
- 实时视频h5
http://www.cnblogs.com/dotfun/p/4286878.html
- Struts之上传
上传的jsp写法: <tr> <td width="50%" align="left">软件上传: <input type=&qu ...
- 如何部署安装软件:vs2010 'VS' Inno Setup
一直以来就是调试程序,生成的文件在debug或者release下,当没有其他资源文件时,这些程序也不用打包,直接就能够运行,但是程序中总会有一些额外的资源文件,视频啊,图片啊.这些需要打包在一个安装文 ...
- json对象中根据主键判断是否有重复数据
function funCheckRepeat() { var ids = $(gridId).jqGrid('getGridParam', 'selarrrow'); if (ids.length ...