【离散化】【DFS】Gym - 101617H - Security Badges
题意:给你一张有向图,每条边有个限制范围,只有权值在限制范围内的人能走这条边,问你权值不超过K的人中,有多少人能从S到T。
K很大,因此我们只处理边的范围的上下界这O(m)个权值能否到达,以防万一,还处理了这些权值+1、-1的可达性。然后去重。离散化出来的这些区间中,两个端点都可达的话,其内部的点也必然可达。当然端点本身也是可达的。
#include<cstdio> #include<cstring> #include<algorithm> #include<set> using namespace std; set<int>S; bool cant[5005],vis[1005]; int first[1005],nex[5005],v[5005],w1[5005],w2[5005],e; void AddEdge(int U,int V,int W1,int W2){ v[++e]=V; w1[e]=W1; w2[e]=W2; nex[e]=first[U]; first[U]=e; } int n,m,K,Sta,End,b[30005],q; bool c[30005]; void dfs(int U){ vis[U]=1; for(int i=first[U];i;i=nex[i]){ if(!cant[i] && !vis[v[i]]){ dfs(v[i]); } } } void Insert(int x){ if(S.find(x)==S.end()){ b[++q]=x; S.insert(x); } } int main(){ int x,y,z1,z2; //freopen("h.in","r",stdin); scanf("%d%d%d%d%d",&n,&m,&K,&Sta,&End); for(int i=1;i<=m;++i){ scanf("%d%d%d%d",&x,&y,&z1,&z2); AddEdge(x,y,z1,z2); if(z1!=1){ Insert(z1-1); } Insert(z1); if(z1!=K){ Insert(z1+1); } if(z2!=1){ Insert(z2-1); } Insert(z2); if(z1!=K){ Insert(z2+1); } } sort(b+1,b+q+1); /*for(int i=1;i<=q;++i){ printf("%d ",b[i]); } puts("");*/ int ans=0; for(int i=1;i<=q;++i){ memset(cant,0,sizeof(cant)); for(int j=1;j<=e;++j){ if(b[i]<w1[j] || b[i]>w2[j]){ cant[j]=1; } } memset(vis,0,sizeof(vis)); dfs(Sta); if(vis[End]){ c[i]=1; ++ans; } } /*for(int i=1;i<=q;++i){ if(c[i]){ printf("%d ",b[i]); } } puts("");*/ for(int i=1;i<q;++i){ if(c[i] && c[i+1]){ ans+=(b[i+1]-b[i]-1); } } printf("%d\n",ans); return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/