标签:
首先读入所有的边与询问。将边按颜色分类。
按颜色进行并查集,
若此并查集内的点<= 100,则100*100/2的枚举是否联通。
若此并查集内的点 > 100,则将与这些点相关的所有询问查一遍。
那么时间复杂度为100*100/2*(M/100),或者为M/100*Q。
极限的时候两种方法都在一亿左右了,而且每次还需要在map里搞一搞,还要查询是否联通,不知道为啥没有超时。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000")
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 6000007
//** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
char c;
while(!d);
x=c-'0';
while(d)p;
return x;
}
template<class T> inline T& RDD(T &x)
{
char c;
while(g,c!='-'&&!isdigit(c));
if (c=='-')
{
x='0'-g;
while(d)n;
}
else
{
x=c-'0';
while(d)p;
}
return x;
}
inline double& RF(double &x) //scanf("%lf", &x);
{
char c;
while(g,c!='-'&&c!='.'&&!isdigit(c));
if(c=='-')if(g=='.')
{
x=0;
double l=1;
while(d)nn;
x*=l;
}
else
{
x='0'-c;
while(d)n;
if(c=='.')
{
double l=1;
while(d)nn;
x*=l;
}
}
else if(c=='.')
{
x=0;
double l=1;
while(d)pp;
x*=l;
}
else
{
x=c-'0';
while(d)p;
if(c=='.')
{
double l=1;
while(d)pp;
x*=l;
}
}
return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
using namespace std;
struct Qu
{
int u,v;
} query[100010];
struct N
{
int u,v,c;
} edge[100010];
bool cmp(N n1,N n2)
{
return n1.c < n2.c;
}
int fa[101000];
bool mark[101000];
map<pair<int,int>,int> M;
vector<int> vec[101000],qu;
int Find(int x)
{
int f = x,t;
while(f != fa[f])
f = fa[f];
while(x != fa[x])
t = fa[x],fa[x] = f,x = t;
return f;
}
void Merge(int u,int v)
{
int fu = Find(u);
int fv = Find(v);
if(fu != fv)
{
fa[fu] = fv;
}
}
inline void Cal()
{
int i,j,k,f,v;
if(qu.size() > 100)
{
for(j = qu.size()-1; j >= 0; --j)
{
f = qu[j];
for(k = vec[f].size()-1; k >= 0; --k)
{
if(Find(f) == Find(vec[f][k]))
M[pair<int,int>(f,vec[f][k])]++;
}
}
}
else
{
for(i = qu.size()-1;i >= 0; --i)
{
f = qu[i];
for(j = i-1;j >= 0; --j)
{
v = qu[j];
if(Find(f) == Find(v))
M[pair<int,int>(min(f,v),max(f,v))]++;
}
}
}
for(j = qu.size()-1; j >= 0; --j)
fa[qu[j]] = qu[j],mark[qu[j]] = false;
qu.clear();
}
int main()
{
int i,j,n,m,u,v,f,k,pre;
scanf("%d %d",&n,&m);
for(i = 1; i <= m; ++i)
scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].c);
int q;
scanf("%d",&q);
for(i = 1; i <= q; ++i)
{
scanf("%d %d",&u,&v);
if(u > v)
swap(u,v);
query[i].u = u;
query[i].v = v;
if(M.find(pair<int,int>(u,v)) == M.end())
{
vec[u].push_back(v);
vec[v].push_back(u);
M.insert(pair<pair<int,int>,int>(pair<int,int>(u,v),0));
}
}
sort(edge+1,edge+m+1,cmp);
for(i = 1; i <= n; ++i)
fa[i] = i;
memset(mark,false,sizeof(mark));
map<pair<int,int>,int>::iterator it;
for(pre = edge[1].c,i = 1; i <= m; ++i)
{
if(pre == edge[i].c)
{
if(mark[edge[i].u] == false)
qu.push_back(edge[i].u),mark[edge[i].u] = true;
if(mark[edge[i].v] == false)
qu.push_back(edge[i].v),mark[edge[i].v] = true;
Merge(edge[i].u,edge[i].v);
}
else
{
pre = edge[i].c;
--i;
Cal();
}
}
Cal();
for(i = 1; i <= q; ++i)
{
printf("%d\n",M[pair<int,int>(query[i].u,query[i].v)]);
}
return 0;
}
Codeforces 506D Mr. Kitayuta's Colorful Graph 并查集+水水的分类讨论+水水的离线预处理
标签:
原文地址:http://blog.csdn.net/zmx354/article/details/42963761