藍橋杯——災後重建

災後重建


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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章