災後重建
Pear市一共有N(<=50000)個居民點,居民點之間有M(<=200000)條雙向道路相連。這些居民點兩兩之間都可以通過雙向道路到達。這種情況一直持續到最近,一次嚴重的地震毀壞了全部M條道路。
震後,Pear打算修復其中一些道路,修理第i條道路需要Pi的時間。不過,Pear並不打算讓全部的點連通,而是選擇一些標號特殊的點讓他們連通。
Pear有Q(<=50000)次詢問,每次詢問,他會選擇所有編號在[l,r]之間,並且 編號 mod K = C 的點,修理一些路使得它們連通。由於所有道路的修理可以同時開工,所以完成修理的時間取決於花費時間最長的一條路,即涉及到的道路中Pi的最大值。
你能幫助Pear計算出每次詢問時需要花費的最少時間麼?這裏詢問是獨立的,也就是上一個詢問裏的修理計劃並沒有付諸行動。
【輸入格式】
第一行三個正整數N、M、Q,含義如題面所述。
接下來M行,每行三個正整數Xi、Yi、Pi,表示一條連接Xi和Yi的雙向道路,修復需要Pi的時間。可能有自環,可能有重邊。1<=Pi<=1000000。
接下來Q行,每行四個正整數Li、Ri、Ki、Ci,表示這次詢問的點是[Li,Ri]區間中所有編號Mod Ki=Ci的點。保證參與詢問的點至少有兩個。
【輸出格式】
輸出Q行,每行一個正整數表示對應詢問的答案。
【樣例輸入】
7 10 4
1 3 10
2 6 9
4 1 5
3 7 4
3 6 9
1 5 8
2 7 4
3 2 10
1 7 6
7 6 9
1 7 1 0
1 7 3 1
2 5 1 0
3 7 2 1
【樣例輸出】
9
6
8
8
【數據範圍】
對於20%的數據,N,M,Q<=30
對於40%的數據,N,M,Q<=2000
對於100%的數據,N<=50000,M<=2*10^5,Q<=50000. Pi<=10^6. Li,Ri,Ki均在[1,N]範圍內,Ci在[0,對應詢問的Ki)範圍內。
資源約定:
峯值內存消耗 < 256M
CPU消耗 < 5000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。
所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。
注意: main函數需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。
注意: 所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。
提交時,注意選擇所期望的編譯器類型。
思想:
①用二維數組(time[][])存儲所有邊
②visited[]用於深度優先搜索中存儲舊點,初始化全部都是舊點;
③對於每一次問詢,使用set()函數,將目標點存入po數組,count爲其長度,將visited[]中對應的點設爲新點;
④調用fun()函數,以po[0]爲基礎點,調用dfs()尋路,尋找它到每個點po[i](1->count-1)的最短路徑。而後取這些最短路徑中的最大值,即爲所求。
⑤我是自己練習時寫的,題中給的測試用例是過了,但是不清楚最大用例能不能按時跑通。
代碼:
#include <iostream>
using namespace std;
int time[5002][5002]={0};
int visited[5002]={1};
int n, m ,q;//city way quest
int po[5002]={1};
int count;
int x;
void set(int l, int r, int k, int c)
{
count=0;
for(int i=l; i<=r; i++)
if(i%k==c)
{
visited[i]=0;
po[count++]=i;
}
}
void reset(int l, int r, int k, int c)
{
for(int i=l; i<=r; i++)
if(i%k==c)
visited[i]=1;
}
void dfs(int temp,int s, int e)
{
if(s == e)
{
if(temp<x) x=temp;
return;
}
if(visited[s]!=0)
return;
visited[s]=1;
for(int i=0; i<n+1; i++)
{
if(time[s][i]!=0)
{
if(temp<time[s][i])
dfs(time[s][i],i,e);
else
dfs(temp,i,e);
}
}
visited[s]=0;
}
void fun()
{
int min =0;
for(int i=1 ;i<count; i++)
{
x=1000000;
dfs(0,po[0],po[i]);
if(x>min) min=x;
}
cout<<min;
}
int main()
{
cin>>n>>m>>q;
int c1, c2;
for(int i=0; i<m; i++)
{
cin>>c1>>c2;
if(c1==c2)
cin>>c1;
else
{
cin>>time[c1][c2];
time[c2][c1]= time[c1][c2];
}
}
for(int i=0; i<q; i++)
{
int l,r,k,c;
cin>>l>>r>>k>>c;
set(l,r,k,c);
fun();
reset(l,r,k,c);
}
return 0;
}