Poj 3613 Cow Relays【Floyd+快速幂】

来源:互联网 发布:kord机枪 知乎 编辑:程序博客网 时间:2024/06/12 22:53

Cow Relays

Time Limit: 1000MS

 

Memory Limit: 65536K

Total Submissions: 6793

 

Accepted: 2660

Description

For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout the pasture.

Each trail connects two different intersections (1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000), each of which is the termination for at least two trails. The cows know the lengthi of each trail (1 ≤ lengthi  ≤ 1,000), the two intersections the trail connects, and they know that no two intersections are directly connected by two different trails. The trails form a structure known mathematically as a graph.

To run the relay, the N cows position themselves at various intersections (some intersections might have more than one cow). They must position themselves properly so that they can hand off the baton cow-by-cow and end up at the proper finishing place.

Write a program to help position the cows. Find the shortest path that connects the starting intersection (S) and the ending intersection (E) and traverses exactly N cow trails.

Input

* Line 1: Four space-separated integers: NTS, and E
* Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: lengthi , I1i , and I2i

Output

* Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.

Sample Input

2 6 6 4

11 4 6

4 4 8

8 4 9

6 6 8

2 6 9

3 8 9

Sample Output

10

Source

USACO 2007 November Gold

 

1、首先我们要理解这样一个问题,如果a【i】【j】表示图的初始邻接矩阵,b【i】【j】==a【i】【j】;

如果c【j】【k】=min(c【j】【k】,a【j】【i】+b【i】【k】){应用Floyd求最短路},其实不难理解,c【】【】得到的邻接矩阵是从b中拿出一条边,从a中拿出一条边构成的,那么如果初始a和

b就是邻接矩阵,那么c【i】【j】现在表示的含义就是从i到j一共经过两条边的最短路。


2、那么推广,如果现在让a【i】【j】=c【i】【j】,那么现在a【i】【j】现在表示的含义就是从i到j一共经过两条边的最短路。此时b【i】【j】不变,还是图的邻接矩阵,如果这时候c【j】【k】=min(c【j】【k】,a【j】【i】+b【i】【k】){应用Floyd求最短路}.那么c【】【】得到的邻接矩阵也是从a中拿出一条边,从b中拿出一条边构成的,然而这时候a中的一条边,其实相当于两条边,那么:c【i】【j】现在表示的含义就是从i到j一共经过三条边的最短路。


3、依次类推,如果需要经过k条边的从i到j的最短路,那么就进行k-1次上述过程即可。因为k可能比较大,而且每一次进行Floyd也是一个不小的开销,所以这k-1次乘法我们用快速幂的方式优化,最终得到正解。


Ac代码:


#include<stdio.h>#include<string.h>#include<stdio.h>#include<map>#include<iostream>#include<algorithm>using namespace std;int head[100000];struct EdgeNode{    int to;    int w;    int next;}e[1000000];int dis3[1005][1005];int dis[1005][1005];int dis2[1005][1005];int q,m,ss,ee,n,cont;void Floyd(int dis[1005][1005],int dis2[1005][1005]){    memset(dis3,0x3f3f3f3f,sizeof(dis3));    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            for(int k=1;k<=n;k++)            {                dis3[j][k]=min(dis3[j][k],dis[j][i]+dis2[i][k]);            }        }    }}void init(){    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            dis[i][j]=dis3[i][j];        }    }}void init2(){    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            dis2[i][j]=dis3[i][j];        }    }}void Slove(int k){    while(k)    {        if(k%2==1)        {            Floyd(dis,dis2);            init();        }        k/=2;        Floyd(dis2,dis2);        init2();    }}int main(){    while(~scanf("%d%d%d%d",&q,&m,&ss,&ee))    {        n=1;        map<int,int >mp;        memset(dis,0x3f3f3f3f,sizeof(dis));        memset(dis2,0x3f3f3f3f,sizeof(dis2));        for(int i=0;i<m;i++)        {            int x,y,w;            scanf("%d%d%d",&w,&x,&y);            if(mp[x]==0)            {                mp[x]=n++;            }            if(mp[y]==0)            {                mp[y]=n++;            }            x=mp[x];y=mp[y];            dis[x][y]=dis[y][x]=w;            dis2[x][y]=dis2[y][x]=w;        }        Slove(q-1);        printf("%d\n",dis[mp[ss]][mp[ee]]);    }}







0 0
原创粉丝点击