hdu 4738 2013杭州赛区网络赛 桥+重边+连通判断 ***

题意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去。

处理重边

边在遍历的时候,第一个返回的一定是之前去的边,所以这条边忽略,然后继续遍历,此时可以通过未遍历的边返回pre

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 using namespace std;
  9 #define MOD 1000000007
 10 const int INF=0x3f3f3f3f;
 11 const double eps=1e-5;
 12 typedef long long ll;
 13 #define cl(a) memset(a,0,sizeof(a))
 14 #define ts printf("*****\n");
 15 int n,m,tt;
 16 /*
 17 * 求 无向图的割点和桥
 18 * 可以找出割点和桥,求删掉每个点后增加的连通块。
 19 * 需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重
 20 */
 21 const int MAXN = 10010;
 22 const int MAXM = 2000010;
 23 struct Edge
 24 {
 25     int to,next;
 26     int w;
 27     bool cut;//是否为桥的标记
 28 }edge[MAXM];
 29 int head[MAXN],tot;
 30 int Low[MAXN],DFN[MAXN],Stack[MAXN];
 31 int Index,top;
 32 bool Instack[MAXN];
 33 bool cut[MAXN];
 34 int add_block[MAXN];//删除一个点后增加的连通块
 35 int bridge;
 36 void addedge(int u,int v,int w)
 37 {
 38     edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut = false;
 39     edge[tot].w = w;
 40     head[u] = tot++;
 41
 42 }
 43 void Tarjan(int u,int pre)
 44 {
 45     int v;
 46     Low[u] = DFN[u] = ++Index;
 47     Stack[top++] = u;
 48     Instack[u] = true;
 49     int son = 0;
 50     int pre_num=0;
 51     for(int i = head[u];i != -1;i = edge[i].next)
 52     {
 53         v = edge[i].to;
 54         if(v == pre&&pre_num==0)
 55         {
 56             pre_num++;
 57             continue;
 58         }
 59         if( !DFN[v] )
 60         {
 61             son++;
 62             Tarjan(v,u);
 63             if(Low[u] > Low[v])Low[u] = Low[v];
 64             //桥
 65             //一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足DFS(u)<Low(v)。
 66             if(Low[v] > DFN[u])
 67             {
 68                 bridge++;
 69                 edge[i].cut = true;
 70                 edge[i^1].cut = true;
 71             }
 72             //割点
 73             //一个顶点u是割点,当且仅当满足(1)或(2) (1) u为树根,且u有多于一个子树。
 74             //(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,
 75             //即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)
 76             if(u != pre && Low[v] >= DFN[u])//不是树根
 77             {
 78                 cut[u] = true;
 79                 add_block[u]++;
 80             }
 81         }
 82         else if( Low[u] > DFN[v])
 83         Low[u] = DFN[v];
 84     }
 85     //树根,分支数大于1
 86     if(u == pre && son > 1)cut[u] = true;
 87     if(u == pre)add_block[u] = son - 1;
 88     Instack[u] = false;
 89     top--;
 90 }
 91 int solve(int N)
 92 {
 93     memset(DFN,0,sizeof(DFN));
 94     memset(Instack,false,sizeof(Instack));
 95     memset(add_block,0,sizeof(add_block));
 96     memset(cut,false,sizeof(cut));
 97     Index = top = 0;
 98     bridge = 0;
 99     for(int i = 1;i <= N;i++)
100         if(!DFN[i])
101             Tarjan(i,i);
102     int ret=INF;
103     for(int u = 1;u <= N;u++)
104     for(int i = head[u];i != -1;i = edge[i].next)
105     if(edge[i].cut)
106     {
107         ret=min(ret,edge[i].w);
108     }
109     if(ret==INF)    return -1;
110     if(ret==0)  ret++;
111     return ret;
112 }
113 int F[MAXN];
114 int find(int x)
115 {
116     if(F[x] == -1)return x;
117     else return F[x] = find(F[x]);
118 }
119 void init()
120 {
121     memset(F,-1,sizeof(F));
122     tot = 0;
123     memset(head,-1,sizeof(head));
124 }
125 void bing(int u,int v)
126 {
127     int t1 = find(u);
128     int t2 = find(v);
129     if(t1 != t2)F[t1] = t2;
130 }
131 int main()
132 {
133     int n,m;
134     #ifndef ONLINE_JUDGE
135     freopen("1.in","r",stdin);
136     #endif
137     while(scanf("%d%d",&n,&m) == 2)
138     {
139         if(n == 0 && m == 0)break;
140         int u,v,w;
141         init();
142         while(m--)
143         {
144             scanf("%d%d%d",&u,&v,&w);
145             if(u == v)continue;
146             addedge(u,v,w);
147             addedge(v,u,w);
148             bing(u,v);
149         }
150         bool flag = true;
151         for(int i = 1; i <= n;i++)
152             if(find(i) != find(1))
153                 flag = false;
154         if(!flag)
155         {
156             printf("0\n");
157             continue;
158         }
159         printf("%d\n",solve(n));
160     }
161     return 0;
162 }
时间: 2024-11-05 18:40:11

hdu 4738 2013杭州赛区网络赛 桥+重边+连通判断 ***的相关文章

hdu 4741 2013杭州赛区网络赛 dfs ***

起点忘记录了,一直wa 代码写的很整齐,看着很爽 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 con

hdu 4751 2013南京赛区网络赛 二分图判断 **

和以前做过的一个二分图颇为相似,以前的是互相不认识的放在一组,这个是互相认识的,本质上是相同的 是 hdu 2444 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace st

hdu 4753 2013南京赛区网络赛 记忆化搜索 ****

看到范围基本可以想到dp了,处理起来有点麻烦 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<map> 7 #include<queue> 8 #include<stack> 9 #include<cmath> 10 #inc

hdu 4035 2011成都赛区网络赛E 概率dp ****

太吊了,反正我不会 1 /* 2 HDU 4035 3 4 dp求期望的题. 5 题意: 6 有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 7 从结点1出发,开始走,在每个结点i都有3种可能: 8 1.被杀死,回到结点1处(概率为ki) 9 2.找到出口,走出迷宫 (概率为ei) 10 3.和该点相连有m条边,随机走一条 11 求:走出迷宫所要走的边数的期望值. 12 13 设 E[i]表示在结点i处,要走出迷宫所要走的边数的期望.E[1]即为所求. 14 15 叶子结点: 16

hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***

新模板 1 /* 2 HDU 4273 Rescue 3 给一个三维凸包,求重心到表面的最短距离 4 模板题:三维凸包+多边形重心+点面距离 5 */ 6 7 #include<stdio.h> 8 #include<algorithm> 9 #include<string.h> 10 #include<math.h> 11 #include<stdlib.h> 12 using namespace std; 13 const int MAXN=

hdu 4041 2011北京赛区网络赛F 组合数+斯特林数 ***

插板法基础知识 斯特林数见百科 1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstring> 5 #define LL long long 6 #define eps 1e-7 7 #define MOD 1000000007 8 using namespace std; 9 int c[2001][2001]={1},stir2[1005][1005]={1};

hdu 4033 2011成都赛区网络赛 余弦定理+二分 **

二分边长,判断最后内角和是否为2pi,注意l与r的选取,保证能组成三角形 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 10000

hdu 4031 2011成都赛区网络赛A题 线段树 ***

就是不知道时间该怎么处理,想了好久,看了别人的题解发现原来是暴力,暴力也很巧妙啊,想不出来的那种  -_-! 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9

hdu 4036 2011成都赛区网络赛F 模拟 **

为了确保能到达终点,我们需要满足下面两个条件 1.能够到达所有山顶 2.能够在遇到苦土豆时速度大于他 二者的速度可以用能量守恒定律做,苦土豆的坐标可通过三角形相似性来做 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> using na