Aizu2971 Consistent Trading
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2971
\(Hash\)
显然,我们可以连边成为一个图,\(u \rightarrow v\)权值为\(z\),则\(v \rightarrow u\)权值为\(\frac{1}{z}\)
那么从任意起点\(s\)到任意终点\(t\)的路径(边权乘积)为兑换关系
显然,对于确定的\(s\)和\(t\),其兑换关系必须相同
所以只有\(s\)到\(t\)的所有路径相同,才能满足题意
\(BFS\)一下,判断类似\(Dijkstra\)
还有一个问题,边权乘积太大,而且还有分数,怎么办?
\(Hash!\)
这样分数也可以用逆元处理了
注意要多模数,取了\(3\)个才过
本来应该写函数的,但是我把代码复制\(3\)遍,代码巨长
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#define N 200005
#define INF 12345678987654321
#define mod1 1000000007
#define mod2 1000000009
#define mod3 39999931
#define ll long long
#define int long long
#define pr pair<ll,int>
using namespace std;
queue<pr>q;
int n,m,tot,x,y,z,in[N];
int head[N],d1[N],d2[N],d3[N],nxt[N],e[N][3];
ll dis[N];
bool vis[N],Previs[N];
ll ksm1(ll x,ll y)
{
ll ans=1;
while (y)
{
if (y&1)
ans=ans*x%mod1;
x=x*x%mod1;
y >>=1;
}
return ans;
}
ll inv1(ll x)
{
return ksm1(x,mod1-2);
}
ll ksm2(ll x,ll y)
{
ll ans=1;
while (y)
{
if (y&1)
ans=ans*x%mod2;
x=x*x%mod2;
y >>=1;
}
return ans;
}
ll inv2(ll x)
{
return ksm2(x,mod2-2);
}
ll ksm3(ll x,ll y)
{
ll ans=1;
while (y)
{
if (y&1)
ans=ans*x%mod3;
x=x*x%mod3;
y >>=1;
}
return ans;
}
ll inv3(ll x)
{
return ksm3(x,mod3-2);
}
void add(int x,int y,int z)
{
tot++;
d1[tot]=y;
d2[tot]=z;
nxt[tot]=head[x];
head[x]=tot;
}
void Clear()
{
tot=0;
memset(head,0,sizeof(head));
memset(vis,false,sizeof(vis));
memset(Previs,false,sizeof(Previs));
}
signed main()
{
scanf("%lld%lld",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
e[i][0]=x,e[i][1]=y,e[i][2]=z;
add(x,y,z);
add(y,x,inv1(z));
}
for (int i=1;i<=n;i++)
dis[i]=0;
for (int i=1;i<=n;i++)
if (!vis[i])
{
in[0]=0;
while (!q.empty())
q.pop();
dis[i]=1;
q.push(make_pair(1,i));
while (!q.empty())
{
pr u=q.front();
q.pop();
if (Previs[u.second])
continue;
vis[u.second]=true;
in[++in[0]]=u.second;
for (int j=head[u.second];j;j=nxt[j])
{
int v=d1[j],cost=d2[j];
if (Previs[v])
continue;
ll o=dis[u.second]*cost%mod1;
if (o!=dis[v]&&dis[v]!=0)
{
puts("No");
return 0;
}
if (dis[v]==0)
q.push(make_pair(o,v));
dis[v]=o;
}
}
for (int j=1;j<=in[0];j++)
Previs[in[j]]=true;
}
Clear();
for (int i=1;i<=m;i++)
{
add(e[i][0],e[i][1],e[i][2]);
add(e[i][1],e[i][0],inv2(e[i][2]));
}
for (int i=1;i<=n;i++)
dis[i]=0;
for (int i=1;i<=n;i++)
if (!vis[i])
{
in[0]=0;
while (!q.empty())
q.pop();
dis[i]=1;
q.push(make_pair(1,i));
while (!q.empty())
{
pr u=q.front();
q.pop();
if (Previs[u.second])
continue;
vis[u.second]=true;
in[++in[0]]=u.second;
for (int j=head[u.second];j;j=nxt[j])
{
int v=d1[j],cost=d2[j];
if (Previs[v])
continue;
ll o=dis[u.second]*cost%mod2;
if (o!=dis[v]&&dis[v]!=0)
{
puts("No");
return 0;
}
if (dis[v]==0)
q.push(make_pair(o,v));
dis[v]=o;
}
}
for (int j=1;j<=in[0];j++)
Previs[in[j]]=true;
}
Clear();
for (int i=1;i<=m;i++)
{
add(e[i][0],e[i][1],e[i][2]);
add(e[i][1],e[i][0],inv3(e[i][2]));
}
for (int i=1;i<=n;i++)
dis[i]=0;
for (int i=1;i<=n;i++)
if (!vis[i])
{
in[0]=0;
while (!q.empty())
q.pop();
dis[i]=1;
q.push(make_pair(1,i));
while (!q.empty())
{
pr u=q.front();
q.pop();
if (Previs[u.second])
continue;
vis[u.second]=true;
in[++in[0]]=u.second;
for (int j=head[u.second];j;j=nxt[j])
{
int v=d1[j],cost=d2[j];
if (Previs[v])
continue;
ll o=dis[u.second]*cost%mod3;
if (o!=dis[v]&&dis[v]!=0)
{
puts("No");
return 0;
}
if (dis[v]==0)
q.push(make_pair(o,v));
dis[v]=o;
}
}
for (int j=1;j<=in[0];j++)
Previs[in[j]]=true;
}
puts("Yes");
return 0;
}