AOJ1330 Never Wait for Weights
考察
n<=100000
m<=100000
なのでn log mとか m log nにしたい気分。
連結判定はUnion Find使えばいい。
わりかしすぐに求められる情報が欲しい、どの情報があると便利か。
Union Find使うので、親との距離がわかっていれば、親との距離の差が答えになるのでは。
ということで、Union Findを少しいじって投げた。
uniteするときにどうやってくっつけるかちょっと手こずった。
#include<iostream> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<functional> #include<stack> #include<queue> #include <iomanip> #include<map> #include<limits> #include<cmath> #include<algorithm> #include<bitset> #include<utility> #include<complex> #include<cstdlib> #include<set> #include<cctype> #define DBG cerr << '!' << endl; #define REP(i,n) for(int (i) = (0);(i) < (n);++i) #define rep(i,s,g) for(int (i) = (s);(i) < (g);++i) #define rrep(i,s,g) for(int (i) = (s);i >= (g);--(i)) #define PB push_back #define MP make_pair #define FI first #define SE second #define SHOW1d(v,n) {for(int W = 0;W < (n);W++)cerr << v[W] << ' ';cerr << endl << endl;} #define SHOW2d(v,i,j) {for(int aaa = 0;aaa < i;aaa++){for(int bbb = 0;bbb < j;bbb++)cerr << v[aaa][bbb] << ' ';cerr << endl;}cerr << endl;} #define ALL(v) v.begin(),v.end() #define Decimal fixed<<setprecision(10) using namespace std; typedef long long ll; typedef vector<int> iv; typedef vector<iv> iiv; typedef vector<string> sv; #define INF 10000000000 struct UF { vector<int> par; // 親 vector<int> sz; // 数 vector<ll> value; // 量 // 初期化 UF(int n):par(n),sz(n),value(n) { for(int i = 0; i < n; i++){ par[i] = i;sz[i] = 1;value[i] = 0; } } // 木の根を求める int find(int x) { if (par[x] == x) { value[x] = 0; return x; } else { int tmp = par[x]; par[x] = find(par[x]); value[x] += value[tmp]; //cout << x << ' ' << value[x] << endl; return par[x]; } } ll retValue(int n) { find(n); // cout << n << "s par is" << par[n] << ' ' << value[n] << endl; return value[n]; } // xとyの属する集合を併合 void unite(int x, int y,ll weight = 0) { int tmpx = x;int tmpy = y; x = find(x); y = find(y); if (x == y) return; par[x] = y; value[x] = -value[tmpx] + weight + value[tmpy]; // cout << "after unite" << x << "value is" << value[x] << ",par is" << par[x] << endl; sz[y] += sz[x]; } // xとyが同じ集合ならtrue bool same(int x, int y) { return find(x) == find(y); } int size(int n){return sz[find(n)];} }; int n,m; int main() { while(cin >> n >> m,n) { UF uf(n); REP(i,m) { char c;int a,b; cin >> c >> a >> b; a--;b--; if(c == '!') { int w;cin >> w; uf.unite(a,b,w); } else { if(!uf.same(a,b)) { cout << "UNKNOWN" << endl; } else { ll A = uf.retValue(a); ll B = uf.retValue(b); cout << A-B << endl; } } } } return 0; }