HDU 4370 0 or 1(spfa+思維建圖+計算最小環)
阿新 • • 發佈:2017-11-24
inf 計算 最小 star while arch mes targe space +X 13+X 14=1
X 14+X 24+X 34=1
X 12+X 22+X 32+X 42=X 21+X 22+X 23+X 24
X 13+X 23+X 33+X 43=X 31+X 32+X 33+X 34
②..X1n+X2n+...Xn-1n=1 於是n號節點的入度為1
③.∑Xki =∑Xij 於是2~n-1號節點的入度必須等於出度
於是3個條件等價於一條從1號節點到n號節點的路徑,故Xij=1表示需要經過邊(i,j),代價為Cij。Xij=0表示不經過邊(i,j)。註意到Cij非負且題目要求總代價最小,因此最優答案的路徑一定可以對應一條簡單路徑。
最終,我們直接讀入邊權的鄰接矩陣,跑一次1到n的最短路即可,記最短路為path。
以上情況設為A
還有如下的情況B:
從1出發,走一個環(至少經過1個點,即不能是自環),回到1;從n出發,走一個環(同理),回到n。
容易驗證,這是符合題目條件的。且A || B為該題要求的充要條件。
由於邊權非負,於是兩個環對應著兩個簡單環。
因此我們可以從1出發,找一個最小花費環,記代價為c1,再從n出發,找一個最小花費環,記代價為c2。
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4370
題目大意:有一個n*n的矩陣Cij(1<=i,j<=n),要找到矩陣Xij(i<=1,j<=n)滿足以下條件:
1.X 12+X 13+...X 1n=1
2.X 1n+X 2n+...X n-1n=1
3.for each i (1<i<n), satisfies ∑X ki (1<=k<=n)=∑X ij (1<=j<=n).
舉個例子, 如果 n=4,上面條件等價於以下情況:
X 12
X 14+X 24+X 34=1
X 12+X 22+X 32+X 42=X 21+X 22+X 23+X 24
X 13+X 23+X 33+X 43=X 31+X 32+X 33+X 34
找出 ∑C ij*X ij(1<=i,j<=n)的最小值。
解題思路:這題主要是考建圖的思維,看了kuangbin寫的才會,下面都是照搬他博客的東西。解題的關鍵在於如何看出這個模型的本質。
3個條件明顯在刻畫未知數之間的關系,從圖論的角度思考問題,容易得到下面3個結論:
①.X12+X13+...X1n=1 於是1號節點的出度為1
②..X1n+X2n+...Xn-1n=1 於是n號節點的入度為1
③.∑Xki =∑Xij 於是2~n-1號節點的入度必須等於出度
於是3個條件等價於一條從1號節點到n號節點的路徑,故Xij=1表示需要經過邊(i,j),代價為Cij。Xij=0表示不經過邊(i,j)。註意到Cij非負且題目要求總代價最小,因此最優答案的路徑一定可以對應一條簡單路徑。
最終,我們直接讀入邊權的鄰接矩陣,跑一次1到n的最短路即可,記最短路為path。
以上情況設為A
還有如下的情況B:
從1出發,走一個環(至少經過1個點,即不能是自環),回到1;從n出發,走一個環(同理),回到n。
容易驗證,這是符合題目條件的。且A || B為該題要求的充要條件。
由於邊權非負,於是兩個環對應著兩個簡單環。
因此我們可以從1出發,找一個最小花費環,記代價為c1,再從n出發,找一個最小花費環,記代價為c2。
故最終答案為min(spfa(1,n),spfa(1,1)+spfa(n,n))。
spfa裏面計算最小環,還需要一點修改,當計算環時(dis[start]==INF且start不入隊,計算所有start能到達的點並入隊)。
代碼:
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #include<cstdio> 6 using namespace std; 7 const int N=3e2+5; 8 const int INF=0x3f3f3f3f; 9 10 int n; 11 int cost[N][N],dis[N]; 12 bool vis[N]; 13 14 int spfa(int s,int e){ 15 memset(dis,0x3f,sizeof(dis)); 16 memset(vis,false,sizeof(vis)); 17 queue<int>q; 18 if(s==e){ 19 for(int i=1;i<=n;i++){ 20 if(i!=s){ 21 q.push(i); 22 dis[i]=cost[s][i]; 23 vis[i]=true; 24 } 25 } 26 } 27 else{ 28 dis[s]=0; 29 q.push(s); 30 } 31 while(!q.empty()){ 32 int k=q.front(); 33 q.pop(); 34 vis[k]=false; 35 for(int i=1;i<=n;i++){ 36 if(dis[k]+cost[k][i]<dis[i]){ 37 dis[i]=dis[k]+cost[k][i]; 38 if(!vis[i]){ 39 q.push(i); 40 vis[i]=true; 41 } 42 } 43 } 44 } 45 return dis[e]; 46 } 47 48 int main(){ 49 while(scanf("%d",&n)!=EOF){ 50 for(int i=1;i<=n;i++){ 51 for(int j=1;j<=n;j++){ 52 scanf("%d",&cost[i][j]); 53 } 54 } 55 int ans=min(spfa(1,n),spfa(1,1)+spfa(n,n)); 56 printf("%d\n",ans); 57 } 58 return 0; 59 }
HDU 4370 0 or 1(spfa+思維建圖+計算最小環)