Gym
来源:互联网 发布:微淘动态在淘宝哪里找 编辑:程序博客网 时间:2024/06/07 19:24
题意:T组数据。n个点 m条边。
无向图。给你a,b,c a-b相连权值为c得到一个无向图。你可以指定一个点为主城市。与这个点相连的所有城市的边权为0,,然后问离这个点的最远距离是多少。
做法:肯定是一个连通分量吧。然后边双连通缩点以后就是一棵树,找树上的直径,首都一定是直径上的点。
直径一定是这棵树上最长的距离。
求树直径做法:先随便找一个点然后一直dfs。一直deep+1到不能再dfs为止。那么这个点肯定是树的一个端点。再让st=这个端点。
反向dfs一次。再找到的一个点肯定是树的另一个端点。那么我已经找到树的两端。再dfs一次把整个树连通。
//china no.1#include <vector>#include <iostream>#include <string>#include <map>#include <stack>#include <cstring>#include <queue>#include <list>#include <stdio.h>#include <set>#include <algorithm>#include <cstdlib>#include <cmath>#include <iomanip>#include <cctype>#include <sstream>#include <functional>#include <stdlib.h>#include <time.h>#include <bitset>using namespace std;#define pi acos(-1)#define endl '\n'#define srand() srand(time(0));#define me(x) memset(x,0,sizeof(x));#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)#define close() ios::sync_with_stdio(0); cin.tie(0);#define FOR(x,n,i) for(int i=x;i<=n;i++)#define FOr(x,n,i) for(int i=x;i<n;i++)#define W while#define sgn(x) ((x) < 0 ? -1 : (x) > 0)#define bug printf("***********\n");typedef long long LL;const int INF=0x3f3f3f3f;const LL LINF=0x3f3f3f3f3f3f3f3fLL;const int dx[]={-1,0,1,0,1,-1,-1,1};const int dy[]={0,1,0,-1,-1,1,-1,1};const int maxn=1e3+10;const int maxx=2e5+100;const double EPS=1e-7;const int MOD=10000007;template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}int vis[maxx],dfn[maxx],low[maxx],bel[maxx],num[maxx],res,pre[maxx];int cont=1,n,m;struct node{ int u,v; LL w;}s[maxx];vector<int>G[maxx],G_new[maxx];queue<int>Q;stack<int>S;vector<node>g[maxx];LL dis1[maxx],dis2[maxx];LL max_len;int st,ed;void tarjan(int fa,int x){ dfn[x]=low[x]=cont++; S.push(x); vis[x]=1; int len=G[x].size(); for(int i=0; i<len; i++) { int nex=G[x][i]; if(fa==nex) continue; if(!vis[nex]) { tarjan(x,nex); low[x]=min(low[x],low[nex]); } else if(vis[nex]==1) low[x]=min(low[x],dfn[nex]); } if(dfn[x]==low[x]) { res++; while(1) { int t=S.top(); S.pop(); bel[t]=res; vis[t]=2; pre[res]=min(pre[res],t);//pre[缩点之前的点] if(x==t)break; } }}void init(){ me(pre);me(vis);(low);me(bel);me(dfn);me(num); for(int i=1;i<=n;i++) { G[i].clear(); pre[i]=INF; g[i].clear(); } me(s); res=0;cont=1;}void dd(int u,int fa,LL len,int flag)//树的直径{ if(flag) dis1[u]=len; if(!flag) dis2[u]=len; if(flag&&len>max_len) st=u,max_len=len; for(int i=0;i<g[u].size();i++) { int v=g[u][i].v; if(v==fa) continue; dd(v,u,len+g[u][i].w,flag); }}void solve(){ cin>>n>>m; init(); for(int i=1;i<=m;i++) { int x,y;LL z; cin>>x>>y>>z; s[i].u=x;s[i].v=y;s[i].w=z; G[x].push_back(y); G[y].push_back(x); } tarjan(-1,1); for(int i=1;i<=m;i++) { int u=bel[s[i].u],v=bel[s[i].v];//缩点之后的树 LL w=s[i].w; if(u!=v) { g[u].push_back(node{0,v,w}); g[v].push_back(node{0,u,w}); } } me(dis1);me(dis2); max_len=-1; dd(1,-1,0,1); ed=st; max_len=-1; dd(st,-1,0,1); swap(st,ed); dd(ed,-1,0,0); LL maxc=LINF; int num=0; for(int i=1;i<=res;i++) { if(max(dis1[i],dis2[i])<maxc) { maxc=max(dis1[i],dis2[i]); num=pre[i]; } if(max(dis1[i],dis2[i])==maxc) num=min(pre[i],num); } cout<<num<<" "<<maxc<<endl;}int main(){ int t; //t=1; close(); cin>>t; for(int cas=1;cas<=t;cas++) solve();}
阅读全文
0 0
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- Gym
- EditorEvent
- 【bzoj1113】 [Poi2008]海报PLA
- 指纹识别分析之enroll流程
- linux下的EDA——DC使用
- 二叉树的七种遍历方式以及按行打印
- Gym
- 百练4982 踩方格
- linux复习之进程基础知识
- Contiki系统关于PROCESS_CONTEXT_BEGIN与PROCESS_CONTEXT_END见解
- H.264句法语义学习
- IO流与多线程
- 【bzoj3524】 [Poi2014]Couriers
- TCP四次挥手中的TIME_WAIT状态存在的理由
- 集合与泛型