1. 程式人生 > >Luogu P2149 [SDOI2009]Elaxia的路線

Luogu P2149 [SDOI2009]Elaxia的路線

一看是purple題很慫。。。我太弱了。。。
但是在這個塊裡面得再刷一題,
另兩題一題是差分,一題是網路流(還是我並不知道是什麼的最小割。。。)
出於lazy的原因並不想學習差分和最小割(並學不會)
又回到了此題,認真看了一遍,
覺得SPFA再列舉兩個最短路中的所有邊看公共邊就好了吧。。。
可是如果有不同的最短路呢,如果有特別多不同的最短路呢
那。。。該怎麼實現呢 那。。。我就不會了啊
又繼續想,從模擬樣例開始,我覺得最短路中的公共路應該連在一起吧,開頭一條邊,中間兩條邊是不會有的
這樣又怎麼樣呢,怎麼樣呢。。。
give up–>看題解
公共路還真是連在一起的!
SPFA沒錯,然後的做法有拓撲和dp等等
我選擇開始打最友善(只看得懂)

的一種解法,

spfa*4 —>對最短路上的邊再建圖—>建完圖找最長鏈

並且認識到了一種判斷邊是否在最短路上的方法

如果st到x的距離+x,y之間距離+y到ed之間距離 那麼x->y這條邊在最短路上
#include<cstdio>
#include<cstring>

int n,m,s1,e1,s2,e2,len,lenn,ans=0;
struct nod1{int x,y,c,next;}a[1000100],a2[1000100];
//。。。試了好幾次才開對了空間,空間還是算不準。。。 
int first[3100],ffirst[3100],max[3100
],b[3100]; int road1[3100],road2[3100],road3[3100],road4[3100]; int ins(int x,int y,int c) {//第一次建圖 spfa) len++; a[len].x=x; a[len].y=y; a[len].c=c; a[len].next=first[x]; first[x]=len; } int inss(int x,int y,int c) {//第二次建圖 搜尋) lenn++; a2[lenn].x=x; a2[lenn].y=y; a2[lenn].c=c; a2[lenn].next=ffirst[x]; ffirst[x]=lenn; } int
spfa(int st,int *road) { int tou=1,wei=2; int f[10010]; f[tou]=st; road[st]=0; memset(b,0,sizeof(b)); b[st]=1; while(tou<wei) { int x=f[tou]; for(int i=first[x];i;i=a[i].next) { int y=a[i].y; if(road[y]>road[x]+a[i].c) { road[y]=road[x]+a[i].c; if(b[y]==0) { b[y]=1; f[wei]=y; wei++; } } } b[x]=0; tou++; } } int find(int x) {//搜尋找最長鏈 if(max[x]!=0)return max[x]; for(int i=ffirst[x];i;i=a2[i].next) { int y=a2[i].y,z=a2[i].c; if(find(y)+z>max[x]) { max[x]=max[y]+z; } } return max[x]; } int buildpic() { for(int i=1;i<=len;i++) { int x=a[i].x,y=a[i].y,z=a[i].c; if(((road1[x]+z+road2[y]==road1[e1])&&(road3[x]+z+road4[y]==road3[e2])) ||((road1[y]+z+road2[x]==road1[e1])&&(road3[x]+z+road4[y]==road3[e2]))) { inss(x,y,z);//printf("!!!!! "); } } } int main() { scanf("%d %d",&n,&m); scanf("%d %d %d %d",&s1,&e1,&s2,&e2); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d %d %d",&x,&y,&z); ins(x,y,z);ins(y,x,z); } memset(road1,63,sizeof(road1)); memset(road2,63,sizeof(road2)); memset(road3,63,sizeof(road3)); memset(road4,63,sizeof(road4)); //4*spfa spfa(s1,road1); spfa(e1,road2); spfa(s2,road3); spfa(e2,road4); //printf("%d %d ",road1[e1],road3[e2]); buildpic();//建圖 for(int i=1;i<=n;i++) { if(max[i]==0) { //printf("11111111"); find(i); //printf("222222222"); }//printf("1111"); if(max[i]>ans)ans=max[i]; } printf("%d",ans); }

在RE了3次後終於A了 這個塊終於過la 以後要注意空間