因为涉及到算法,所以就不把全部题目放到一个文章里了,方便以后找相关算法的时候查看。
HDU 2874
题意:给定一些点和边,询问两点之间是否连通,若连通,输出最短距离。
思路:离线tarjan算法,与其他裸题的区别就是要判是否在一棵树上。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 100005 #define inf 1<<28 #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define FOR(i,s,t) for(int i=(s);i<=(t);++i) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) #define PII pair<int,int> using namespace std; struct kdq { int e,l,next ; } ed[Max] ,ee[2000005] ; int head1[Max] ; int nume = 0 ; int head[Max] ; int vis[Max] ; int num ; int dis[Max] ; int f[Max] ; int ans[Max * 10] ; void add(int s ,int e, int l) { ed[num].e = e ; ed[num].l = l ; ed[num].next = head[s] ; head[s] = num ++ ; } void adde(int s,int e,int l ) { ee[nume].e = e ; ee[nume].next = head1[s] ; ee[nume].l = l ; head1[s] = nume ++ ; } int aaa ; void init(int n ) { mem(head,-1); mem(head1 ,-1) ; nume = 0 ; mem(vis,0) ; num = 0 ; mem(dis,0) ; for (int i = 0 ; i <= n; i++)f[i] = i ; mem(ans,0) ; } int find(int x ) { return x == f[x] ? x :f[x] = find(f[x]) ; } int nnn ; void dfs(int now,int pre,int l) { //cout <<nnn<<endl; dis[now] = dis[pre] + l ; for (int i = head[now] ; i != -1 ; i = ed[i].next ) { int e = ed[i].e ; int l = ed[i].l ; if(e == pre)continue; dfs(e,now,l) ; f[e] = now ; } vis[now] = nnn ; // cout <<vis[now]<<endl; for (int i = head1[now] ; i != -1 ;i = ee[i].next ) { int e = ee[i].e; if(vis[e]) { //cout <<vis[e]<<endl; if(find(e) == aaa||vis[e] == nnn)//判断是否在这棵树上找到该点 ans[ee[i].l] = dis[e] + dis[now] - 2 * dis[find(e)] ; else ans[ee[i].l] = -1 ; } } } int main() { int T ; int n ,m , k ; while(scanf("%d%d%d",&n,&m,&k) != EOF) { init(n) ; for (int i = 0 ; i < m ; i ++) { int a , b , c ; scanf("%d%d%d",&a,&b,&c) ; add(a,b,c) ; add(b,a,c) ; } for (int i = 0 ; i < k ; i ++) { int a ,b ; scanf("%d%d",&a,&b); adde(a,b,i); adde(b,a,i) ; } nnn = 1 ; for (int i = 1 ;i <= n ;i ++) { if(!vis[i]) { aaa = i ; nnn ++ ; dfs(i,0,0) ; } } for (int i = 0 ; i < k ; i ++) if(ans[i] == -1 ) puts("Not connected"); else printf("%d\n",ans[i]) ; } return 0; }
HDU 2586
裸题
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 100005 #define inf 1<<28 #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define FOR(i,s,t) for(int i=(s);i<=(t);++i) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) #define PII pair<int,int> using namespace std; struct kdq { int e,l,next ; }ed[Max] ; int head[Max] ; bool vis[Max] ; int num ; int dis[Max] ; int f[Max] ; int ans[Max] ; void add(int s ,int e, int l) { ed[num].e = e ; ed[num].l = l ; ed[num].next = head[s] ; head[s] = num ++ ; } vector<PII>q[Max];; void init(int n ) { mem(head,-1); mem(vis,0) ; num = 0 ; mem(dis,0) ; for (int i = 0 ;i <= n; i++)f[i] = i ,q[i].clear() ; mem(ans,0) ; } int find(int x ) { return x == f[x] ? x :f[x] = find(f[x]) ; } int dfs(int now,int pre) { for (int i = head[now] ;i != -1 ;i = ed[i].next ) { int e = ed[i].e ; int l = ed[i].l ; if(e == pre)continue; dis[e] = dis[now] + l ; dfs(e,now) ; f[e] = now ; } vis[now] = 1 ; int k = q[now].size() ; for (int i = 0 ;i < k ;i ++) { int e = q[now][i].first ; if(vis[e]) { ans[q[now][i].second] = dis[e] + dis[now] - 2 * dis[find(e)] ; } } } int main() { int T ; cin >> T ; while( T -- ) { int n ,m ; cin >> n >> m ; init(n) ; for (int i = 0 ;i < n - 1 ;i ++) { int a , b , c ; scanf("%d%d%d",&a,&b,&c) ; add(a,b,c) ; add(b,a,c) ; } for (int i = 0 ;i < m ;i ++) { int a ,b ; scanf("%d%d",&a,&b); q[a].push_back(mp(b,i)) ; q[b].push_back(mp(a,i)) ; } dfs(1,0) ; for (int i = 0 ;i < m ;i ++) cout <<ans[i]<<endl; } return 0; }