链接
http://codeforces.com/gym/101615/problem/G
题解1
打比赛的时候自己瞎
yy
y
y
了一个做法,就是每个点
s
s
记录一个集合,表示哪些数能走到这里,初始点是
1...k
1...
k
,我用
spfa
s
p
f
a
来更新,比方说我用
u
u
去更新,边上的集合是
s
s
,那就
箭头表示更新
不用真的存
1...k
1...
k
,最后的集合的边界肯定是输入的某条边的某个上下界,我把输入数据离散化,然后开一个
M
M
级别大小的布尔数组表示集合中这个数字是否存在就行了
代码1
#include <bits/stdc++.h>
#define maxn 1010
#define maxm 5010
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
struct Set
{
bool v[maxm<<1];
Set(){cl(v);}
}d[maxn], e[maxm];
int head[maxn], to[maxm], nex[maxm], l[maxm], r[maxm], S, dest, N, M, tmp[maxm<<1], tot, K, T, vis[maxn];
void adde(int a, int b, int v1, int v2){to[++tot]=b;l[tot]=v1;r[tot]=v2;nex[tot]=head[a];head[a]=tot;}
Set bing(Set &a, Set &b)
{
int i;
Set ans;
for(i=1;i<=T;i++)ans.v[i]=a.v[i] or b.v[i];
return ans;
}
Set jiao(Set &a, Set &b)
{
int i;
Set ans;
for(i=1;i<=T;i++)ans.v[i]=a.v[i] and b.v[i];
return ans;
}
int read(int x=0)
{
int f=1, c;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
void ls(int &x){x=lower_bound(tmp+1,tmp+T+1,x)-tmp;}
void init()
{
int i, u, v, a, b, x=0, j;
N=read(), M=read(), K=read();
S=read(), dest=read();
for(i=1;i<=M;i++)
{
u=read(), v=read(), a=read(), b=read();
adde(u,v,a,b);
tmp[++T]=a-1, tmp[++T]=b;
}
tmp[++T]=K;
sort(tmp+1,tmp+T+1);
for(i=1;i<=T;i++)if(tmp[i]!=tmp[i-1])tmp[++x]=tmp[i];T=x;
for(i=1;i<=tot;i++)ls(l[i]), ls(r[i]);
for(i=1;i<=tot;i++)for(j=l[i];j<=r[i];j++)e[i].v[j]=1;
}
bool in(Set &a, Set &b)
{
int i;
for(i=1;i<=T;i++)if(a.v[i]==1 and b.v[i]==0)return false;
return true;
}
void spfa()
{
Set s;
int i, now, p;
queue<int> q;
for(i=1;i<=T;i++)d[S].v[i]=1;
q.push(S);
while(!q.empty())
{
now=q.front(); q.pop();
vis[now]=0;
for(p=head[now];p;p=nex[p])
{
s=jiao(d[now],e[p]);
if(!in(s,d[to[p]]))
{
d[to[p]]=bing(s,d[to[p]]);
if(!vis[to[p]])vis[to[p]]=1, q.push(to[p]);
}
}
}
}
void show()
{
int i, ans=0, j;
for(i=1;i<=T;i++)
{
if(d[dest].v[i]==1)
{
ans+=tmp[i]-tmp[i-1];
}
}
printf("%d",ans);
}
int main()
{
init();
spfa();
show();
return 0;
}
题解2
大家好像都不是我上面那种脑洞做法,听过了这道题的人说,离散之后直接用验证下那些边界值是否合法就行了
我:……
代码2
#include <bits/stdc++.h>
#define maxn 1010
#define maxm 5010
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int head[maxn], to[maxm], nex[maxm], l[maxm], r[maxm], S, dest, N, M, tmp[maxm<<2], tot, K, T, vis[maxn], ok[maxm<<2];
void adde(int a, int b, int v1, int v2){to[++tot]=b;l[tot]=v1;r[tot]=v2;nex[tot]=head[a];head[a]=tot;}
int dfs(int pos, int k)
{
int p;
vis[pos]=1;
for(p=head[pos];p;p=nex[p])
if(!vis[to[p]] and k>=l[p] and k<=r[p])dfs(to[p],k);
}
int read(int x=0)
{
int f=1, c;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
void ls(int &x){x=lower_bound(tmp+1,tmp+T+1,x)-tmp;}
void init()
{
int i, u, v, a, b, x=0, j;
N=read(), M=read(), K=read();
S=read(), dest=read();
for(i=1;i<=M;i++)
{
u=read(), v=read(), a=read(), b=read();
adde(u,v,a,b);
tmp[++T]=a-1, tmp[++T]=b;
}
sort(tmp+1,tmp+T+1);
}
int main()
{
int i, ans=0;
init();
for(i=1;i<=T;i++)
{
cl(vis);
dfs(S,tmp[i]);
if(vis[dest])ans+=tmp[i]-tmp[i-1];
}
printf("%d",ans);
return 0;
}