Cherry symbol JZOJ6376] [[completely inked cherry]

description


analysis

  • FIG undirected any two points on the flow does not exceed the maximum \ (2 \) which is a cactus described

  • Since the maximum flow equal to the minimum cut, if one side of the two rings, the at least two end cut off \ (3 \) cost

  • For the cactus, seeking minimum cut between two points, then either cut a bridge, two cutting edges on either a ring

  • Top right side of the smallest ring must be cut, then put the edge off, together with the other right Collage Collage, right on the ring, the equivalent cut in advance

  • FIG then becomes a tree, cut the minimum path between any two points is the minimum

  • The \ (n-1 \) strip inserted into the descending side of the tree, so that the front of the back does not affect the contribution

  • Set Maintenance and check each set of \ (\ P ^ {SUM (. 1-I) n-}, \ SUM P ^ I \) , the contribution due to the distributive property of the multiplication is the entire collection of sets of two contributions

  • I started \ (naive \) think to use \ (tarjan \) shrink ring, fought only to find I \ (TOO \) \ (Young \)

  • \ (m \) after the edges descending order to direct the tree structure, the recording side constituting a ring, and then find the edges endpoints \ (the LCA \) , the force on the right side of the path plus

  • Be careful not to be too violent, it is important doubled after veteran


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 300005
#define MAXM 500005
#define ha 998244353
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])

using namespace std;

ll last[MAXM*2],next[MAXM*2],tov[MAXM*2],len[MAXM*2];
ll fa[MAXN],falen[MAXN],depth[MAXN];
ll sumin[MAXN],sumi[MAXN],anc[MAXN][20];
ll n,m,p,tot,ans,cnt;
bool bz[MAXN];

struct edge
{
    ll x,y,z;
}a[MAXM],b[MAXM];

inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
    while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline ll max(ll x,ll y){return x>y?x:y;}
inline ll min(ll x,ll y){return x<y?x:y;}
inline bool cmp(edge a,edge b){return a.z>b.z;}
inline ll getfa(ll x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
inline ll pow(ll x,ll y)
{
    ll z=1;
    while (y){if (y&1)z=z*x%ha;x=x*x%ha,y>>=1;}
    return z;
}
inline ll lca(ll x,ll y)
{
    if (depth[x]<depth[y])swap(x,y);
    fd(i,19,0)if (depth[anc[x][i]]>=depth[y])x=anc[x][i];
    if (x==y)return x;
    fd(i,19,0)if (anc[x][i]!=anc[y][i])x=anc[x][i],y=anc[y][i];
    return anc[x][0];
}
inline void link(ll x,ll y,ll z){next[++tot]=last[x],last[x]=tot,tov[tot]=y,len[tot]=z;}
inline void dfs(ll x,ll y)
{
    fo(i,1,19)anc[x][i]=anc[anc[x][i-1]][i-1];
    rep(i,x)if (tov[i]!=y)fa[tov[i]]=anc[tov[i]][0]=x,falen[tov[i]]=len[i],depth[tov[i]]=depth[x]+1,dfs(tov[i],x);
}
int main()
{
    freopen("T2.in","r",stdin);
    //freopen("sakura.in","r",stdin);
    //freopen("sakura.out","w",stdout);
    n=read(),m=read(),p=read();
    fo(i,1,n)fa[i]=i;
    fo(i,1,m)a[i].x=read(),a[i].y=read(),a[i].z=read();
    sort(a+1,a+m+1,cmp);
    fo(i,1,m)
    {
        ll x=a[i].x,y=a[i].y,z=a[i].z,xx=getfa(x),yy=getfa(y);
        if (xx!=yy)fa[xx]=yy,link(x,y,z),link(y,x,z);
        else b[++cnt].x=x,b[cnt].y=y,b[cnt].z=z;
    }
    depth[1]=1,dfs(1,0),tot=0;
    fo(i,1,cnt)
    {
        ll x=b[i].x,y=b[i].y,z=b[i].z,LCA=lca(x,y);
        if (LCA!=x){falen[x]+=z;while (fa[x]!=LCA)x=fa[x],falen[x]+=z;}
        if (LCA!=y){falen[y]+=z;while (fa[y]!=LCA)y=fa[y],falen[y]+=z;}
    }
    fo(i,2,n)a[++tot].x=i,a[tot].y=fa[i],a[tot].z=falen[i];
    sort(a+1,a+n,cmp);
    fo(i,1,n)sumin[i]=pow(p,(i-1)*n),sumi[i]=pow(p,i),fa[i]=i;
    fo(i,1,n-1)
    {
        ll x=a[i].x,y=a[i].y,z=a[i].z,xx=getfa(x),yy=getfa(y);
        (ans+=(z*sumin[xx]%ha*sumi[yy]%ha+z*sumin[yy]%ha*sumi[xx]%ha)%ha)%=ha;
        fa[xx]=yy,(sumin[yy]+=sumin[xx])%=ha,(sumi[yy]+=sumi[xx])%=ha;
    }
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/horizonwd/p/11628440.html