hdu-5786(補圖最短路)
阿新 • • 發佈:2018-11-02
最短 can 我們 ace int 不用 scan csharp std
題意:給你n個點,m條無向邊,問你這n個點構成的完全圖,不用那m條邊,由一個s出現的單源最短路
解題思路:首先,暴力建圖不行,點太多,那麽我們就按照它的規則來,把m條邊建好,但是建的這個圖表示不走的方法,然後我們需要用一個東西來保存去除這些直接相連的邊的其它點,用set
代碼:
#include<iostream> #include<algorithm> #include<cstring> #include<set> #include<queue> #include<cstdio> using namespace std; const int maxn=200500; const int inf=0x3f3f3f3f; struct Edge { int next; int to; }edge[maxn]; int head[maxn]; int visit[maxn]; int dist[maxn]; int cnt; int n,m; int start; set<int>s; void add(int u,int v) { edge[cnt].next=head[u];edge[cnt].to=v;head[u]=cnt++; } void init() { memset(head,-1,sizeof(head)); cnt=0; } void bfs(int u) { fill(dist+1,dist+1+n,inf); queue<int>q; q.push(u); set<int>s1,s2;//s2保存未拓展的點,既還沒有到達可能由其它點中轉的點; dist[u]=0; for(int i=1;i<=n;i++) if(i!=u) s1.insert(i);//先把所有點加入 while(!q.empty()) { int now=q.front(); q.pop(); for(int i=head[now];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!s1.count(v))//如果這個點被直接連邊,那麽這條邊不算 continue; s1.erase(v); s2.insert(v);//把這個點扔到沒法拓展的點裏面 } for(set<int>::iterator it=s1.begin();it!=s1.end();it++) { q.push(*it); dist[*it]=dist[now]+1; } s1.swap(s2); s2.clear(); } } int main() { int tt; int u,v; while(scanf("%d",&tt)!=EOF) { while(tt--) { init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); add(u,v);add(v,u); } scanf("%d",&start); bfs(start);//開始 int cot=0; for(int i=1; i<=n; i++) { if(i==start) continue;cot++; if(dist[i]==inf) cout<<-1; else cout<<dist[i]; if(cot<=n-2) cout<<" "; } cout<<endl; } } }
hdu-5786(補圖最短路)