题意:求标号最小的最大割点.(删除该点后,指定点#sink能到达的点数减少最多).

析:由于不知道要去掉哪个结点,又因为只有100个结点,所以我们考虑用一个暴力,把所有的结点都去一次,然后用并查集去判断。

当然也可以用割点和桥的模板,最后再判断一下,哪个点后面的点有多少就好。

代码如下:

并查集+暴力:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e3 + 100;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *Hex[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
int x;
vector<P> v;
int p[105];
int Find(int x) { return x == p[x] ? x : p[x] = Find(p[x]); } int main(){
while(scanf("%d", &n) == 1 && n){
scanf("%d", &x);
scanf("%d", &m);
int u, vv;
v.clear();
for(int i = 0; i < m; ++i){
scanf("%d %d", &u, &vv);
v.push_back(P(u, vv));
}
int ans = 0, cnt = 0;
for(int i = 1; i <= n; ++i){
if(i == x) continue;
for(int j = 1; j <= n; ++j) p[j] = j;
for(int j = 0; j < v.size(); ++j){
u = v[j].first;
vv = v[j].second;
if(u == i || vv == i) continue;
int x = Find(u);
int y = Find(vv);
if(x != y) p[y] = x;
}
map<int, int> mp;
map<int, int> :: iterator it;
for(int j = 1; j <= n; ++j)
if(i != j) ++mp[Find(j)];
if(mp.size() <= 1) continue;
int y = Find(x);
if(cnt < n-mp[y]-1){
cnt = n-mp[y]-1;
ans = i;
}
} printf("%d\n", ans);
}
return 0;
}

割点和桥:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e2 + 5;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *Hex[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
vector<int> G[maxn];
bool cut[maxn];
int low[maxn], dfn[maxn], vis[maxn], ans[maxn]; void dfs(int cur, int fa, int d){
vis[cur] = 1;
dfn[cur] = low[cur] = d;
int u = 0;
for(int i = 0; i < G[cur].size(); ++i){
int v = G[cur][i];
if(v != fa && 1 == vis[v]){
if(dfn[v] < low[cur]) low[cur] = dfn[v];
}
if(!vis[v]){
dfs(v, cur, d+1);
++u;
if(low[v] < low[cur]) low[cur] = low[v];
if((fa == -1 && u > 1) || (fa != -1 && low[v] >= dfn[cur])) cut[cur] = true;
}
}
vis[cur] = 2;
} void dfs1(int u){
vis[u] = 1;
ans[u] = 1;
for(int i = 0; i < G[u].size(); ++i){
int v = G[u][i];
if(vis[v]) continue;
dfs1(v);
ans[u] += ans[v];
}
} int main(){
int rt;
while(scanf("%d", &n) == 1 && n){
scanf("%d", &rt);
scanf("%d", &m);
for(int i = 1; i <= n; ++i) G[i].clear();
int u, v;
for(int i = 0; i < m; ++i){
scanf("%d %d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(dfn, 0, sizeof dfn);
memset(cut, false, sizeof cut);
memset(low, 0, sizeof vis);
memset(vis, 0, sizeof vis);
dfs(rt, -1, 0);
memset(vis, 0, sizeof vis);
memset(ans, 0, sizeof ans);
dfs1(rt); int anss = 0, cnt = 0;
for(int i = 1; i <= n; ++i){
if(cut[i] && cnt < ans[i]){
cnt = ans[i];
anss = i;
}
}
printf("%d\n", anss);
}
return 0;
}

UVaLive 7456 Least Crucial Node (并查集+暴力 或者 求割点)的更多相关文章

  1. UVALive 7456 Least Crucial Node (并查集)

    Least Crucial Node 题目链接: http://acm.hust.edu.cn/vjudge/contest/127401#problem/C Description http://7 ...

  2. UVALive 7456 Least Crucial Node

    题目链接 题意: 给定一个无向图,一个汇集点,问哪一个点是最关键的,如果有多个关键点,输出序号最小的那个. 因为数据量比较小,所以暴力搜索就行,每去掉一个点,寻找和汇集点相连的还剩几个点,以此确定哪个 ...

  3. UVALive - 6910 (离线逆序并查集)

    题意:给处编号从1~n这n个节点的父节点,得到含有若干棵树的森林:然后再给出k个操作,分两种'C x'是将节点x与其父节点所连接的支剪短:'Q a b'是询问a和b是否在同一棵树中. 题解:一开始拿到 ...

  4. uvalive 4730王国kingdom(并查集+线段树)

     题意:有T组測试数据.每组数据的N表示有N个城市,接下来的N行里每行给出每一个城市的坐标(0<=x,y<=1000000),然后有M(1<M<200000)个操作,操作有 ...

  5. UVALive 6910 Cutting Tree(并查集应用)

    总体来说,这个题给的时间比较长,样例也是比较弱的,别的方法也能做出来. 我第一次使用的是不合并路径的并查集,几乎是一种暴力,花了600多MS,感觉还是不太好的,发现AC的人很多都在300MS之内的过得 ...

  6. POJ 1562 Oil Deposits (并查集 OR DFS求联通块)

    Oil Deposits Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14628   Accepted: 7972 Des ...

  7. BZOJ 4668: 冷战 并查集&&暴力LCA(雾)

    利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...

  8. UVALive - 5031 Graph and Queries (并查集+平衡树/线段树)

    给定一个图,支持三种操作: 1.删除一条边 2.查询与x结点相连的第k大的结点 3.修改x结点的权值 解法:离线倒序操作,平衡树or线段树维护连通块中的所有结点信息,加个合并操作就行了. 感觉线段树要 ...

  9. fzu 2087并查集的运用求最小生成树的等效边

    //对数组排序后,对于边相同并且边的两端不在一个集合内的一定是等效边或者必加边, //第一数数,第二合并集合 #include<stdio.h> #include<stdlib.h& ...

随机推荐

  1. cms完整视频教程+源码 孔浩老师 全131讲

    话不多说,请看如下链接,  项目在此文件夹目录下:  JAVA专区>3.深入Java Web>3.1.cms项目 很多反馈说无效 本次 2016.09.12 发布最新链接 链接:https ...

  2. php 中函数获取可变参数的方法, 这个语法有点像 golang 语言中的

    原文呢:http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.strict Onl ...

  3. start_kernel——mm_init_owner

    全部任务都具有自己的内存,启动阶段中的当前任务必须具备属于自己的内存. mm_init_owner()函数传递init_mm和init_task參数 mm/init-mm.c struct mm_st ...

  4. SolidEdge 工程图中如何控制是否显示爆炸图组装线

    右击视图,点击性质,取消勾选"显示流线"   即可取消爆炸视图的装配线              

  5. Intel Edision —— 从SSH无法连接到systemd

    前言 原创文章,转载引用务必注明链接.如有疏漏,欢迎斧正. 最近在试用Wyliodrin,安装过程中出现了两个问题,一是无法使用SSH登录到Edison:二是EDISON磁盘的问题.分别涉及到syst ...

  6. vue的安装以及语法介绍

    #需要用到一个vue文件,还有一个自己的js文件main.js<!DOCTYPE html> <html lang="en"> <head> & ...

  7. Filter注入对象

    由于没有在web.xml文件中加上<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter ...

  8. linux 输入子系统(4) intput_dev 接口描述

    Name struct input_dev - represents an input device Synopsis struct input_dev { const char * name; // ...

  9. 程序设计之另一种读写函数---writev,readv

    read()和write()系统调用每次在文件和进程的地址空间之间传送一块连续的数据.但是,应用有时也需要将分散在内存多处地方的数据连续写到文件中,或者反之.在这种情况下,如果要从文件中读一片连续的数 ...

  10. ExtJs4.2 开发问题总结

    1. 在开发treegrid中,store属性autoLoad:false没有作用,还会默认自动加载.目前解决办法在control下监听treegrid的afterrender,当加载完后,再调一次s ...