usaco Fence Loops
生活随笔
收集整理的這篇文章主要介紹了
usaco Fence Loops
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一開始完全沒思路,百度了一下了解到是用floyd求最小環,于是我去百度了一下這個算法了解到了很多我之前不了解的flyod算法。好了既然知道用啥算法就寫吧,然后發現懵逼了。這題是邊的序號沒有點。得自己化成點圖。。。。。。。。于是我苦思冥想。終于想到了一個方法本來想著如果不對的話就一步一步的改誰知道竟然第一遍就all test OK 了哈哈。
floyd求最小環我轉到了上篇博客了。接下來說說我是怎么化邊為點的吧。先用e1,e2兩個容器存好各個邊的鄰邊。用vis數組記錄這邊與其他邊連接的端點是哪一個。vis[s][a]=1;
表示s的1端點與a邊相連。具體在代碼里說
/*
ID:jinbo wu
TASK:fence6
LANG:C++
*/
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int g[250][250];
map<int,pair<int,int> > m;
vector<int> e1[110],e2[110];
int l[110];
int dist[250][250];
int vis[110][110];
int mark;
void floyd()
{int ans=INF;for(int k=1;k<mark;k++){for(int i=1;i<k;i++)for(int j=i+1;j<k;j++){ans=min(ans,dist[i][j]+g[i][k]+g[k][j]);}for(int i=1;i<mark;i++)for(int j=1;j<mark;j++){dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);}}cout<<ans<<endl;
}
void f(int n)
{mark=1;//用Mark分別給邊的兩端加編號for(int i=1;i<=n;i++){if(!m[i].first)//m[i].first為真說明這邊的端點1跟別的邊有連接而且被編過號了{m[i].first=mark;mark++;//點的編號加一為了給后面的端點編號}for(int j=0;j<e1[i].size();j++)//遍歷與i的一端點所連的邊{int v=e1[i][j];if(!vis[v][i])//編號為v的這一邊與i相連,vis值為0表示v邊的2端點與i的1端點相連賦予相同的值。m[v].second=m[i].first;elsem[v].first=m[i].first;}if(!m[i].second){m[i].second=mark;mark++;}for(int j=0;j<e2[i].size();j++)//同理{int v=e2[i][j];if(!vis[v][i])m[v].second=m[i].second;elsem[v].first=m[i].second;}}for(int i=1;i<=n;i++)//每個邊上兩個點以及邊的長度l[i];{int u=m[i].first;int v=m[i].second;dist[u][v]=dist[v][u]=g[u][v]=g[v][u]=l[i];}floyd();}
int main()
{freopen("fence6.in","r",stdin);freopen("fence6.out","w",stdout);int n,a;int s,n1s,n2s;cin>>n;memset(dist,0x3f,sizeof(dist));memset(g,0x3f,sizeof(g));int t=n;while(t--){cin>>s;cin>>l[s]>>n1s>>n2s;for(int i=0;i<n1s;i++){cin>>a;e1[s].push_back(a);vis[s][a]=1;}for(int i=0;i<n2s;i++){cin>>a;e2[s].push_back(a);vis[s][a]=0;}}f(n);}
總結
以上是生活随笔為你收集整理的usaco Fence Loops的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求几部类似《霍比特星人3五军之战》那种大
- 下一篇: 《庾楼新岁》第一句是什么