背景
这次小杉来到了经典美剧《越狱》的场景里……
他被抓起来了(-.-干嘛幻想这么郁闷的场景……)。
小杉身为新一代的Scofield,在挖了半个月之后终于挖通牢房里的地道。
在地道里,无数的管道路线困惑了他。
(若对情节有任何疑问,请观看原剧)
描述
小杉看了看自己的纹身,明白了整个管道网是由N个小房间和若干小房间之间的单向的管道组成的。
小房间编号为不超过N的正整数。
对于某个管道,小杉只能在人品不超过一定程度时通过。
小杉一开始在房间1,现在小杉想知道,每个小房间他最多能够以人品多少的状态到达。
注意,小杉的人品在出发以后是不会改变的。
格式
输入格式
每组测试数据的
第一行有一个正整数N(1<=N<=2000)。
接下来若干行描述管道,每行三个正整数A,B,R(1<=A,B<=N),表示A房间有一条到达B房间的管道,且小杉的人品不超过R时可以通过(注意从B房间不可由此管道到达A房间,即管道是单向的)
整个输入数据以一行0 0 0结束
特别地,对于30%的数据,有N<=100
输出格式
对每组测试数据输出N-1行,分别表示对于2到N号的小房间,小杉最多能够以人品多少的状态到达。
样例1
样例输入1
4
1 2 30
1 3 20
2 3 25
3 4 30
2 4 20
0 0 0
样例输出1
30
25
25
限制
每个测试点1s
提示
对于样例数据:
小杉最多能够在人品为30的情况下到达小房间2(1->2)
小杉最多能够在人品为25的情况下到达小房间3(1->2->3)
小杉最多能够在人品为25的情况下到达小房间4(1->2->3->4)
方法一:
取巧的方法,成功地把数据被氵过去了
二分查找答案+BFS判断是否能到终点,时间复杂度N*M*log(maxn)(正解还没有看,先氵一波)
方法二:
(应该是正解吧)
先按边的大小排序,然后不断地把大边往图里建,然后每次从这条大边做一次 spfa s p f a 修改答案
显然,这里的时间复杂度远小于 N∗M N ∗ M (反正我不会算,就瞎写一个吧)
氵题的代码
#include
#include
using namespace std;
int n,tot,maxn;
int lnk[2005],q[2005],ans[2005];
bool vis[2005];
struct edge
{
int nxt,y,v;
} e[4000005];
int readln()
{
int x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while ('0'<=ch&&ch<='9') x=x*10+ch-48,ch=getchar();
return x;
}
void add(int x,int y,int v)
{
tot++;e[tot].nxt=lnk[x];lnk[x]=tot;e[tot].y=y;e[tot].v=v;
}
int max(int x,int y){return x>y?x:y;}
bool bfs(int limit,int goal)
{
memset(vis,false,sizeof(vis));
int head=0,tail=1;
q[1]=1;vis[1]=true;
while (headint x=q[++head];
for (int i=lnk[x];i;i=e[i].nxt)
{
int y=e[i].y,v=e[i].v;
if (vis[y]==false&&v>=limit) {
if (y==goal) return true;
q[++tail]=y;vis[y]=true;
}
}
}
return false;
}
int main()
{
n=readln();
int x,y,z=1;
while (true) {
x=readln();y=readln();z=readln();
if (x+y+z==0) break;
add(x,y,z);maxn=max(maxn,z);
}
for (int i=2;i<=n;i++)
{
int l=1,r=maxn,mid;
while (l<=r)
{
mid=(l+r)>>1;
if (bfs(mid,i)) l=mid+1,ans[i]=mid; else r=mid-1;
}
}
for (int i=2;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}
正解
#include
#include
#define maxn 2005
using namespace std;
int n,tot,cnt;
int lnk[maxn],q[maxn],ans[maxn],a[maxn*maxn],b[maxn*maxn],c[maxn*maxn];
struct edge
{
int nxt,v,y;
} e[maxn*maxn];
int readln()
{
int x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while ('0'<=ch&&ch<='9') x=x*10+ch-48,ch=getchar();
return x;
}
void add(int x,int y,int v)
{
cnt++;e[cnt].nxt=lnk[x];lnk[x]=cnt;e[cnt].y=y;e[cnt].v=v;
}
int min(int x,int y){return x<y?x:y;}
bool spfa(int x)
{
int head=0,tail=1;
q[1]=x;
while (headint x=q[++head];
for (int i=lnk[x];i;i=e[i].nxt)
{
int y=e[i].y,v=min(e[i].v,ans[x]);
if (v>ans[y])
{
ans[y]=v;q[++tail]=y;
}
}
}
return false;
}
void qsort(int l,int r)
{
int i=l,j=r,mid=c[rand()%(r-l+1)+l],t;
do {
while (c[i]>mid) i++;
while (c[j]if (i<=j) {
t=a[i];a[i]=a[j];a[j]=t;
t=b[i];b[i]=b[j];b[j]=t;
t=c[i];c[i]=c[j];c[j]=t;
i++;j--;
}
} while (i<=j);
if (iif (lint main()
{
n=readln();
while (true) {
int x,y,z;
x=readln();y=readln();z=readln();
if (x+y+z==0) break;
a[++tot]=x;b[tot]=y;c[tot]=z;
}
qsort(1,tot);
ans[1]=0x7fffffff;
for (int i=1;i<=tot;i++)
{
add(a[i],b[i],c[i]);
spfa(a[i]);
}
for (int i=2;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}