正解:网络流

解题报告:

传送门$QwQ$

题目好长昂,,,大概概括下$QwQ$.就说有$n$个节点$m$条边,然后要求每次走的路径都不一样,问最多能走多少次,然后在次数最多的前提下问路径最短是多少$QwQ$

$umm$看到询问就不难想到费用流,,,?就最小费用最大流嘛.

但是这里要强调下题目,,,就说它的要求其实是说每个点只能经过一次,,,然后我愚蠢地当作每条边只能经过一次打完了才发现不对嘤嘤嘤,,,

然后说下怎么建图?首先因为它是对点有限制所以就拆点呗?拆开的点之间连流量为1费用为0的边嘛.然后其他的就照着边连流量为1费用为$w$的边嘛.然后因为家和学校是起终点而且又能经过无数次所以和$ST$连$inf$的边而且拆开的点之间也连$inf$的边嘛.最后那个$(1,n)$边只能走一次的限制其实是麻油意义的?因为我直接在连边的时候就限制了这个$QwQ$

$over$

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define int long long
#define t(i) edge[i].to
#define n(i) edge[i].nxt
#define w(i) edge[i].wei
#define fy(i) edge[i].fy
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define e(i,x) for(ri i=head[x];~i;i=n(i)) const int N=+,inf=1e9;
int head[N],ed_cnt=-,S,T,dis[N],fr_nod[N],fr_ed[N],cost,fl,n,m;
bool vis[N];
struct ed{int to,nxt,wei,fy;}edge[N<<]; il int read()
{
rc ch=gc;ri x=;rb y=;
while(ch!='-' && (ch>'' || ch<''))ch=gc;
if(ch=='-')ch=gc,y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=gc;
return y?x:-x;
}
il void ad(ri x,ri y,ri z,ri p)
{edge[++ed_cnt]=(ed){x,head[y],z,p};head[y]=ed_cnt;edge[++ed_cnt]=(ed){y,head[x],,-p};head[x]=ed_cnt;}
il bool spfa()
{
queue<int>Q;Q.push(S);memset(dis,,sizeof(dis));dis[S]=;vis[S]=;
while(!Q.empty())
{
ri nw=Q.front();Q.pop();vis[nw]=;
e(i,nw)
{
if(w(i) && fy(i)+dis[nw]<dis[t(i)])
{dis[t(i)]=dis[nw]+fy(i);fr_nod[t(i)]=nw;fr_ed[t(i)]=i;if(!vis[t(i)])Q.push(t(i)),vis[t(i)]=;}
}
}
if(dis[T]==dis[T+])return ;
ri flow=dis[T+];
for(ri i=T;i!=S;i=fr_nod[i])flow=min(flow,w(fr_ed[i]));
for(ri i=T;i!=S;i=fr_nod[i])w(fr_ed[i])-=flow,w(fr_ed[i]^)+=flow;
cost+=flow*dis[T];fl+=flow;return ;
} signed main()
{
//freopen("2153.in","r",stdin);freopen("2153.out","w",stdout);
n=read();m=read();memset(head,-,sizeof(head));S=;T=n<<|;
rp(i,,n-)ad(i+n,i,,);ad(+n,,inf,);ad(n+n,n,inf,);ad(,S,inf,);ad(T,n+n,inf,);
rp(i,,m){ri x=read(),y=read(),z=read();ad(y,x+n,,z);}
while(spfa());printf("%lld %lld\n",fl,cost);
return ;
}
05-25 18:36