您的位置:首页 > 编程语言 > PHP开发

【最短路】解题报告

2011-11-01 09:42 253 查看
4.最短路(path.c/cpp)
[问题描述]

给定一个包含N个点,M条边的无向图,每条边的边权均为1。

再给定K个三元组(A,B,C),表示从A点走到B点后不能往C点走。注意三元组是有序的,如可以从B点走到A点再走到C。

现在你要在K个三元组的限制下,找出1号点到N号点的最短路径,并输出任意一条合法路径,会有Check检查你的输出。

[输入格式]

输入文件第一行有三个数N,M,K,意义如题目所述。

接下来M行每行两个数A,B,表示A,B间有一条边。

再下面K行,每行三个数(A,B,C)描述一个三元组。

[输出格式]

输出文件共两行数,第一行一个数S表示最短路径长度。

第二行S+1个数,表示从1到N所经过的节点。

[样例输入]

4 4 2

1 2

2 3

3 4

1 3

1 2 3

1 3 4

[样例输出]

4

1 3 2 3 4

[数据范围]

对于40%的数据满足N≤10,M≤20,K≤5。

对于100%的数据满足N≤3000,M≤20000,K≤100000。

 

这道题是一道拆点的题,不过也可以用广搜来做,每次记录父亲就行了。

一开始我就卡在了这点上,走到下一个点,但是并不知道这个状态是由哪一个父亲派生出来的,但是其实就是这么简单,对每个队列中的元素都记录父亲。

广搜:

#include <cstdio>

struct node
{
long y;
long z;
node* next;
};
node* g[3002][3002];

long n;long m;long k;
long que[1100000];
long que2[1100000];
long fa[3002];
bool map[3002][3002];

void insert(long x,long z,long y)
{
node* tmp = new node;
tmp -> z = z;
tmp -> y = y;
tmp -> next = g[x][y];
g[x][y] = tmp;
}

void output(long p)
{
if (fa[p]==0)
{
printf("%ld ",que[p]);
return;
}
output(fa[p]);
printf("%ld ",que[p]);
}

bool check(long a,long b)
{
node* ths = g[fa[a]][b];

while (ths)
{
if (ths->z==a) return false;
ths = ths->next;
}
return true;
}

void bfs()
{
long l= 0;long r= 0;
r++;
que[r] = 1;
while (l<r)
{
long now = que[++l];
for (long i=1;i<n+1;i++)
{
if (now == i)continue;
if (map[now][i]&&check(l,i))
{
map[now][i] = false;
r++;
fa[r] = l;
que[r] = i;
que2[r] = que2[l]+1;
if (i==n)
{
printf("%ld\n",que2[r]);
output(r);
return;
}
}
}
}
}

int main()
{
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
scanf("%ld%ld%ld",&n,&m,&k);
for (long i=1;i<m+1;i++)
{
long a;long b;
scanf("%ld%ld",&a,&b);
map[a][b] = true;
map[b][a] = true;
}
for (long i=1;i<k+1;i++)
{
long a;long b;long c;
scanf("%ld%ld%ld",&a,&b,&c);
insert(a,b,c);
}
bfs();
return 0;
}


spfa+拆点

意思容易理解,只是代码不好写,因为结构体太多了。容易混淆

拆点关键就在于,对于hash、dist、还有记录方案的g统统都要增加一维。

上个方案的bfs中,hash增加了一维也是基于这个原因,因为不能从上一个点到这个点来了,但是还会有其他的路到这个点来

#include <cstdio>

struct node
{
long z;
node* next;
};
node* g[3002][3002];

struct node1
{
long index;
node1* next;
};

struct tnode
{
long f;
long i;
};

long n;long m;long k;
tnode que[100000];
bool map[3002][3002];
node1* dian[3002];
bool used[3002][3002];
long dist[3002][3002];
long fangan[3002][3002];

void insert1(long x,long y)
{
node1* tmp = new node1;
tmp->index = y;
tmp->next = dian[x];
dian[x] = tmp;
}

void insert(long x,long y,long z)
{
node* tmp = new node;
tmp -> z = z;
tmp -> next = g[x][y];
g[x][y] = tmp;
}

bool can(long a,long b,long c)
{
node* ths = g[a][b];

while (ths)
{
if (ths->z==c) return false;
ths = ths->next;
}
return true;
}

void spfa()
{
for (long i=0;i<n+1;i++)
{
for (long j=0;j<n+1;j++)
{
dist[i][j] = 0x7fff0000;
}
}
used[1][1] = true;
dist[1][1] = 0;
long l = 0;
long r = 1;
que[r].f=1;
que[r].i=1;
while (l<r)
{
l++;
tnode now = que[l];
used[now.f][now.i] = false;
node1* ths = dian[now.i];
while (ths)
{
if (can(now.f,now.i,ths->index)&&dist[now.i][ths->index]>dist[now.f][now.i]+1)
{
dist[now.i][ths->index]=dist[now.f][now.i]+1;
fangan[now.i][ths->index] = l;
if (!used[now.i][ths->index])
{
used[now.i][ths->index] = true;
r++;
que[r].i = ths->index;
que[r].f = now.i;
}
}
ths = ths -> next;
}
}
}

void output(long a,long b)
{
if(b==1)
{
printf("1 ");
return;
}
tnode* la = &que[fangan[a][b]];
output(la->f,la->i);
printf("%ld ",b);
}

int main()
{
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
scanf("%ld%ld%ld",&n,&m,&k);
for (long i=1;i<m+1;i++)
{
long a;long b;
scanf("%ld%ld",&a,&b);
insert1(a,b);
insert1(b,a);
}
for (long i=1;i<k+1;i++)
{
long a;long b;long c;
scanf("%ld%ld%ld",&a,&b,&c);
insert(a,b,c);
}
spfa();
long ans = 0x7fff0000;
long t = 0;
for (long i=1;i<n;i++)
{
if (dist[i]
<ans)
{
ans=dist[i]
;
t=i;
}
}
printf("%ld\n",ans);
output(t,n);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  insert output struct c im ini