标签:push #define mes lin each test struct false str
题意:n个点m条边的有向图,问存在多少个点使得去掉这个点及相连的边后起点和终点不再联通。
思路:非常easy想到Tarjan算法求割点,可是略微一想就会知道不正确,由于Tarjan算法求的是整个图的割点,而这里题目仅仅要求能使起点和终点不连通的点。
然后我们先用SPFA求出一条最短路径,那么要求的“割点”一定都在这条路径上,细致想想就会知道。求出最短路径后从起点dfs。直到找到距离start最远的且在最短路径上的点v。那么v就是一个割点,这时更新start。令start=v,反复上面的dfs直到终点。
为什么这么做呢?你能够在纸上画绘图就会非常快明确了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v) memset ((t) , v, sizeof(t))
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf printf
#define DBG pf("Hi\n")
typedef long long ll;
using namespace std;
#define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 100010;
const int MAXM = 300010;
const int N = 1005;
int n,m;
struct Edge
{
int u,v,next;
}edge[MAXM];
int head[MAXN],dist[MAXN],pre[MAXN];
bool inq[MAXN],mark[MAXN],vis[MAXN];
int num,start,End;
void init()
{
num=0;
mem(head,-1);
}
void addedge(int u,int v)
{
edge[num].u=u;
edge[num].v=v;
edge[num].next=head[u];
head[u]=num++;
}
bool SPFA(int s,int t)
{
mem(inq,false);
mem(mark,false);
mem(dist,INF);
mem(pre,-1);
dist[s]=0;
inq[s]=true;
queue<int>Q;
Q.push(s);
while(!Q.empty())
{
int u=Q.front();
Q.pop();
inq[u]=false;
for (int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].v;
if (dist[v]>dist[u]+1)
{
dist[v]=dist[u]+1;
pre[v]=u;
if (!inq[v])
{
inq[v]=true;
Q.push(v);
}
}
}
}
if (dist[t]>=INF) return false;
int x=t;
mem(mark,false);
while (x!=-1)
{
mark[x]=true;
x=pre[x];
}
return true;
}
void dfs(int u)
{
if (vis[u]) return ;
vis[u]=true;
for (int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].v;
if (mark[v]&&dist[v]>=dist[start]) //由于有重边,所以一定要加等号,坑了我好久=-=
{
start=v;
continue;
}
dfs(v);
}
return ;
}
//void dfs(int u) //第二种写法
//{
// for (int i=head[u];~i;i=edge[i].next)
// {
// int v=edge[i].v;
// if (vis[v]) continue;
// vis[v]=true;
// if (mark[v]&&dist[v]>dist[start])
// {
// start=v;
// continue;
// }
// dfs(v);
// }
// return ;
//}
int main()
{
#ifndef ONLINE_JUDGE
freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
int i,j,u,v;
while (~sff(n,m))
{
init();
for (i=0;i<m;i++)
{
sff(u,v);
addedge(u,v);
}
sff(start,End);
if (!SPFA(start,End))
{
pf("%d\n",n);
continue;
}
int ans=0;
mem(vis,false);
while (start!=End)
{
// printf("++%d\n",start);
dfs(start);
// printf("--%d\n",start);
ans++;
}
printf("%d\n",ans+1);
}
return 0;
}
Key Vertex (hdu 3313 SPFA+DFS 求起点到终点路径上的割点)
标签:push #define mes lin each test struct false str
原文地址:https://www.cnblogs.com/zhchoutai/p/8928955.html