標籤:style blog http color io os ar for 資料
vijos1107環遊大同80天
學習了一下求樹的最長鏈的方法
最簡單的思路就是兩次dfs
兩次dfs分別有什麼用呢?
第一次dfs,求出某個任意的點能到達的最遠的點
第二次dfs,從所搜到的最遠的點倒搜回去.
為什麼需要兩次呢?
其實很容易想通第一遍dfs的起始點或許並不是最長鏈的起點
從最遠的點倒搜到的最長的鏈就是所求的解
(因為最長鏈一定經過這個最遠的點啊...
這裡注意題目表述:
假設任意的兩個風景點都有且僅有一條路徑(無迴路)相連。顯然,任意一個風景點都可以作為遊覽路線的起點或者終點。
這裡就保證了題目中只有一個連通塊,也就是從可走的任意點開始第一遍dfs都是可行的
mark一個小技巧的東西:
因為之前沒有看清題目..就把所有的可以走的點都兩遍dfs了..
T是肯定的...但是被D說dfs寫得太醜...之前用vis[][] 記錄是否搜過該點,需要每次dfs之前都memset一次,很浪費時間
學長表示可以每次dfs的時候+a,然後比較是否和之前遞迴進來的相等即可
然後附上這題代碼:
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;bool f[1001][1001];int vis[1001][1001];int temp=0,ans=0,maxn=0,maxx=0,markx,marky;int dx,dy;int n,m;char s;bool f1;void dfs(int x,int y,int sum){if(x<0 || x>n || y<0 || y>m || (vis[x][y]==vis[markx][marky] && !f1)){if(sum>maxx){ maxx=sum; dx=x; dy=y; } return;}vis[x][y]++;f1=0;if(f[x-1][y]) dfs(x-1,y,sum+1);if(f[x+1][y]) dfs(x+1,y,sum+1);if(f[x][y-1]) dfs(x,y-1,sum+1);if(f[x][y+1]) dfs(x,y+1,sum+1);}int main(){//freopen("data.txt","r",stdin);scanf("%d%d",&n,&m);memset(f,false,sizeof(f));for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ cin>>s; if(s==‘.‘) f[i][j]=1; }memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ ans=0; if(f[i][j]){ f1=1; markx=i;marky=j; dfs(i,j,0); break; } }f1=1;markx=dx;marky=dy;dfs(dx,dy,0);printf("%d",maxx);return 0;}
編譯成功
測試資料 #0: Accepted, time = 46 ms, mem = 5384 KiB, score = 20
測試資料 #1: Accepted, time = 0 ms, mem = 5364 KiB, score = 20
測試資料 #2: Accepted, time = 421 ms, mem = 5364 KiB, score = 20
測試資料 #3: Accepted, time = 187 ms, mem = 5412 KiB, score = 20
測試資料 #4: Accepted, time = 0 ms, mem = 5368 KiB, score = 20
Accepted, time = 654 ms, mem = 5412 KiB, score = 100
沒有0ms過.....代碼寫得太挫了...
VIJOS1107 求樹的最長鏈