把每个点(除了1,n)之外拆成i和i1,两点间连一条容量为1,费用为零的边,这样可以限定,每个点只被跑到一次,那么之后跑一个最流量为2的最小费用流就可以了。
至于其他边,流量设为1,保证每个边只被跑到一次。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <set> #include <map> #include <string> #include <list> #include <cstdlib> #include <queue> #include <stack> #include <cmath> #define ALL(a) a.begin(), a.end() #define clr(a, x) memset(a, x, sizeof a) #define fst first #define snd second #define pb push_back #define lowbit(x) (x&(-x)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep1(i,x,y) for(int i=x;i<=y;i++) #define rep(i,n) for(int i=0;i<(int)n;i++) using namespace std; const double eps = 1e-10; typedef long long LL; typedef long long ll; typedef pair<int, int> pii; const int oo =0x3f3f3f3f; const int maxn=2020; const int maxm=30000; struct Edge { int u, v, cap, flow, cost, nxt; Edge(int u, int v, int c, int f, int co, int nxt):u(u), v(v), cap(c), flow(f), cost(co), nxt(nxt) {} Edge() {} }; struct MCMF { int n, m, s, t; Edge edge[maxm]; int head[maxn], tot; int inq[maxn], d[maxn], p[maxn], a[maxn]; void init(int _n) { n=_n; tot=0; clr(head, -1); } void add(int u, int v, int cap, int cost) { edge[tot]=Edge(u, v, cap, 0, cost, head[u]); head[u]=tot++; edge[tot]=Edge(v, u, 0, 0, -cost, head[v]); head[v]=tot++; } bool spfa(int s, int t, int& flow, int& cost) { clr(d, 0x3f); clr(inq, 0); d[s]=0, inq[s]=1, p[s]=0, a[s]=oo; queue<int> q; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; for(int i=head[u]; ~i; i=edge[i].nxt) { Edge& e=edge[i]; if(e.cap>e.flow && d[e.v]>d[u]+e.cost) { d[e.v]=d[u]+e.cost; p[e.v]=i; a[e.v]=min(a[u], e.cap-e.flow); if(!inq[e.v]) { q.push(e.v); inq[e.v]=1; } } } } if(d[t]==oo)return false; flow+=a[t]; cost+=a[t]*d[t]; int u=t; while(u!=s) { edge[p[u]].flow+=a[t]; edge[p[u]^1].flow-=a[t]; u=edge[p[u]].u; } return true; } int MinCost(int s, int t) { int flow=0, cost=0; while(spfa(s, t, flow, cost)); return cost; } } net; int S,T,n,m; int main() { while(scanf("%d %d",&n,&m)==2) { S = 0 , T = 2*n+1; net.init(T+10); rep1(i,1,m) { int u,v,cost; scanf("%d %d %d",&u,&v,&cost); net.add(u+n,v,1,cost); } rep1(i,1,n) net.add(i,i+n,(i==1 || i==n?2:1),0); net.add(S,1,2,0); int ans = net.MinCost(S,n+n); printf("%d\n",ans); } return 0; } /** 6 11 1 2 23 1 3 12 1 4 99 2 5 17 2 6 73 3 5 3 3 6 21 4 6 8 5 2 33 5 4 5 6 5 20 **/