n点m边的无向图,额外给k条边,走这k条边需要票(你只有一张),求s->t最短路,
n≤500,m≤1000,k≤1000
先求从源汇点出发的最短路,枚举k条边,
ans=min(f1(a)+w(a,b)+f2(b))
gbn最近打算穿过一个森林,但是他比较傲娇,于是他决定只走一些特殊的道路,他打算只沿着满足如下条件的(A,B)道路走:存在一条从B出发回家的路,比所有从A出发回家的路径都短。你的任务是计算一共有多少条不同的回家路径。其中起点的编号为1,终点的编号为2.
预处理出最短路,转DAG,dp
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
struct Edge{
int from,to,dist;
};
struct HeapNode {
int d,u;
bool operator< (const HeapNode& rhs) const {
return d > rhs.d;
}
};
#define MAXN (1010)
struct Dijkstra {
int n,m;
vector<Edge> edges;
vector<int> G[MAXN];
bool done[MAXN];
int d[MAXN];
int p[MAXN]; //最短路中上一条边
int pnode[MAXN];
void addedge(int u,int v,int w){
edges.pb((Edge){u,v,w});
G[u].pb(m++);
}
void addedge2(int u,int v,int w) {
addedge(u,v,w);addedge(v,u,w);
}
void init(int _n){
n=_n; m = 0;
Rep(i,n) G[i].clear();
edges.clear();
}
void dijkstra(int s) {
priority_queue<HeapNode> Q;
Rep(i,n) d[i]=INF,pnode[i]=-1;
d[s]=0;
MEM(done)
Q.push((HeapNode){0,s});
while(!Q.empty()) {
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if (done[u]) continue;
done[u]=1;
int mm=G[u].size();
Rep(i,mm) {
Edge e = edges[G[u][i]];
if (d[e.to]>d[u]+e.dist) {
d[e.to]=d[u]+e.dist;
p[e.to]=G[u][i];
pnode[e.to]=u;
Q.push((HeapNode){d[e.to],e.to});
}
}
}
}
}S1;
int n,m;
vi G[MAXN];
int indegree[MAXN];
namespace topsort{
int b[MAXN];
int q[MAXN*4];
int topsort()
{
MEM(b) b[0]=1;
int head_=1,tail=0;
Rep(i,n)
if (indegree[i]==0)
{
q[++tail]=i;
}
while (head_<=tail)
{
int now=q[head_];
int m=SI(G[now]);
Rep(i,m) {
int v=G[now][i];
indegree[v]--; b[v]+=b[now];
if (indegree[v]==0)
{
q[++tail]=v;
}
}
head_++;
}
return b[1];
}
}
int main()
{
// freopen("uva10917.in","r",stdin);
// freopen(".out","w",stdout);
while(cin>>n &&n) {
m=read();
S1.init(n);
Rep(i,m) {
int a=read()-1,b=read()-1;
S1.addedge2(a,b,read());
}
S1.dijkstra(1);
Rep(i,n) indegree[i]=0,G[i].clear();
Rep(k,m) {
int i=S1.edges[k*2].from,j=S1.edges[k*2].to;
if (S1.d[i]>S1.d[j]) G[i].pb(j),indegree[j]++;
else if (S1.d[i]<S1.d[j]) G[j].pb(i),indegree[i]++;
}
cout<<topsort::topsort()<<endl;
}
return 0;
}
给一张n点m边的无向带边权图,你需要删一条边,
使 ∑i∑jdis(i,j) 最小
枚举起点,枚举删的边,跑dijkstra,复杂度 O(nm2logn)
对于某个起点i,删的边只有在最短路树上才会改变 ∑jdis(i,j) ,所以复杂度降到 O(n2mlogn)
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (0x3f3f3f3f3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,m,L;
struct Edge{
int from,to,dist;
};
struct HeapNode {
int d,u;
bool operator< (const HeapNode& rhs) const {
return d > rhs.d;
}
};
#define MAXN (100+10)
#define MAXM (2000+10)
struct Dijkstra {
int n,m;
vector<Edge> edges;
vector<int> G[MAXN];
bool done[MAXN];
ll d[MAXN];
int p[MAXN]; //最短路中上一条边
int pnode[MAXN];
void addedge(int u,int v,int w){
edges.pb((Edge){u,v,w});
G[u].pb(m++);
}
void addedge2(int u,int v,int w) {
addedge(u,v,w);addedge(v,u,w);
}
void init(int _n){
n=_n; m = 0;
Rep(i,n) G[i].clear();
edges.clear();
}
ll dijkstra(int s,int E = -1 ) {
priority_queue<HeapNode> Q;
Rep(i,n) d[i]=INF,pnode[i]=-1,p[i]=-1;
d[s]=0;
MEM(done)
Q.push((HeapNode){0,s});
while(!Q.empty()) {
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if (done[u]) continue;
done[u]=1;
int mm=G[u].size();
Rep(i,mm) {
if (E!=-1&&E/2==G[u][i]/2) continue;
Edge e = edges[G[u][i]];
if (d[e.to]>d[u]+e.dist) {
d[e.to]=d[u]+e.dist;
p[e.to]=G[u][i];
pnode[e.to]=u;
Q.push((HeapNode){d[e.to],e.to});
}
}
}
ll ans=0;
Rep(i,n) ans+=(INF == d[i] ) ? L : d[i] ;
return ans;
}
ll T[MAXM]; // the cost if delete ith edge
int p2[MAXN]; //最短路中上一条边
void calc(int s){ //only consider started at Point s
ll c=dijkstra(s);
Rep(i,m+1) T[i]+=c;
memcpy(p2,p,sizeof(int)*n);
Rep(i,n) if (p2[i]!=-1) {
T[p2[i]|1]+= dijkstra(s,p2[i])-c;
}
}
void solve(){
MEM(T)
Rep(i,n) calc(i);
ll ans=T[0];
Rep(i,m) ans=max(ans,T[i]);
cout<<T[m]<<' '<<ans<<endl;
}
}S1;
int main()
{
// freopen("uva1416.in","r",stdin);
// freopen(".out","w",stdout);
while(cin>>n>>m>>L) {
S1.init(n);
Rep(i,m) {
int a=read()-1,b=read()-1;
S1.addedge2(a,b,read());
}
S1.solve();
}
return 0;
}
从s到t,每次经过一个村庄要缴纳1个单位的货物,经过一个城镇时,每20个货物就要缴纳一个(不足向上取整),求字典序最小的最少花费路径。
从终点向起点走Dijkstra。
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (0x3f3f3f3f3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,h[1000];
char h2[1000];
void prework(){
Fork(i,'a','z') h[i]=i-'a',h2[i-'a']=i;
Fork(i,'A','Z') h[i]=i-'A'+26,h2[i-'A'+26]=i;
}
struct Edge{
int from,to,dist;
};
struct HeapNode {
int d,u;
bool operator< (const HeapNode& rhs) const {
return d > rhs.d;
}
};
#define MAXN (100)
struct Dijkstra {
int n,m;
vector<Edge> edges;
vector<int> G[MAXN];
bool done[MAXN];
ll d[MAXN];
int p[MAXN]; //最短路中上一条边
int pnode[MAXN];
void addedge(int u,int v,int w){
edges.pb((Edge){u,v,w});
G[u].pb(m++);
}
void addedge2(int u,int v,int w) {
addedge(u,v,w);addedge(v,u,w);
}
void init(int _n){
n=_n; m = 0;
Rep(i,n) G[i].clear();
edges.clear();
}
void dijkstra(int s,ll w) {
priority_queue<HeapNode> Q;
Rep(i,n) d[i]=INF,pnode[i]=-1;
d[s]=w;
MEM(done)
Q.push((HeapNode){0,s});
while(!Q.empty()) {
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if (done[u]) continue;
done[u]=1;
int mm=G[u].size();
Rep(i,mm) {
Edge e = edges[G[u][i]];
if (e.from<26) e.dist=1;
else {
e.dist=d[u]/19;
while((d[u]+e.dist)-ceil(((double)d[u]+e.dist)/20)<d[u]) ++e.dist;
}
if (d[e.to]>d[u]+e.dist|| (d[e.to]==d[u]+e.dist&&h2[pnode[e.to]]>h2[u]) ) {
d[e.to]=d[u]+e.dist;
p[e.to]=G[u][i];
pnode[e.to]=u;
Q.push((HeapNode){d[e.to],e.to});
}
}
}
}
}S1;
int main()
{
// freopen("uva10537.in","r",stdin);
// freopen(".out","w",stdout);
prework();
int kcase=1;
while(cin>>n && n!=-1) {
S1.init(26*2);
For(i,n) {
char a[2],b[2];
cin>>a>>b;
S1.addedge2(h[a[0]],h[b[0]],0);
}
ll w;
char st[2],ed[2];
cin>>w>>st>>ed;
printf("Case %d:\n",kcase++);
S1.dijkstra(h[ed[0]],w);
printf("%lld\n",S1.d[h[st[0]]]);
int u;
for(u=h[st[0]];S1.pnode[u]!=-1;u=S1.pnode[u]) printf("%c-",h2[u]);
cout<<h2[u]<<endl;
}
return 0;
}
给定一个n点m边带正权有向图,求平均权值最小的回路,无解输’No cycle found’
二分求解,注意无解当且仅当图中无环
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,m;
struct Edge{
int from,to;
double dist;
};
#define MAXN (1000)
struct BellmanFord {
int n,m;
vector<Edge> edges;
vi G[MAXN];
bool inq[MAXN];
double d[MAXN];
int cnt[MAXN],p[MAXN];
void addedge(int u,int v,int w){
edges.pb((Edge){u,v,w});
G[u].pb(m++);
}
void addedge2(int u,int v,int w) {
addedge(u,v,w);addedge(v,u,w);
}
void init(int _n){
n=_n; m = 0;
Rep(i,n) G[i].clear();
edges.clear();
}
bool negativeCycle() {
queue<int> Q;
MEM(inq) MEM(cnt)
Rep(i,n) d[i]=0,inq[i]=1,Q.push(i);
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = 0;
int mm=G[u].size();
Rep(i,mm) {
Edge e = edges[G[u][i]];
if (d[e.to]>d[u]+e.dist ) {
d[e.to]=d[u]+e.dist;
p[e.to]=G[u][i];
if (!inq[e.to]) {
Q.push(e.to);
inq[e.to]=1;
if (++cnt[e.to]>n) return 1;
}
}
}
}
return 0;
}
bool check(double x) {
Rep(i,m) edges[i].dist -=x;
bool ret = negativeCycle();
Rep(i,m) edges[i].dist +=x;
return ret;
}
}S1;
int main()
{
// freopen("uva11090.in","r",stdin);
// freopen(".out","w",stdout);
int T=read();
For(kcase,T) {
cin>>n>>m;
S1.init(n);
For(i,m) {
int a=read()-1,b=read()-1;
S1.addedge(a,b,read());
}
double L = 0 , R = 10000000;
printf("Case #%d: ",kcase);
if (!S1.check(R+1)) {
puts("No cycle found.");
continue;
}
while(R-L>1e-3) {
double m= (L+R)/2;
if (S1.check(m)) R=m; else L=m;
}
printf("%.2lf\n",R);
}
return 0;
}
已知带权有向图,每次可以选一个结点v和整数d,把终点为v的边的权值减d,起点为v的边的权值加d,求让所有边权的最小值非负且尽量大。
设节点v上的d为sum_v
则, wa,b−x<=db−da
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,m;
struct Edge{
int from,to;
double dist;
};
#define MAXN (520)
struct BellmanFord {
int n,m;
vector<Edge> edges;
vi G[MAXN];
bool inq[MAXN];
double d[MAXN];
int cnt[MAXN],p[MAXN];
void addedge(int u,int v,int w){
edges.pb((Edge){u,v,w});
G[u].pb(m++);
}
void addedge2(int u,int v,int w) {
addedge(u,v,w);addedge(v,u,w);
}
void init(int _n){
n=_n; m = 0;
Rep(i,n) G[i].clear();
edges.clear();
}
bool negativeCycle() {
queue<int> Q;
MEM(inq) MEM(cnt)
Rep(i,n) d[i]=0,inq[i]=1,Q.push(i);
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = 0;
int mm=G[u].size();
Rep(i,mm) {
Edge e = edges[G[u][i]];
if (d[e.to]>d[u]+e.dist ) {
d[e.to]=d[u]+e.dist;
p[e.to]=G[u][i];
if (!inq[e.to]) {
Q.push(e.to);
inq[e.to]=1;
if (++cnt[e.to]>n) return 1;
}
}
}
}
return 0;
}
bool check(double x) {
Rep(i,m) edges[i].dist -=x;
bool ret = negativeCycle();
Rep(i,m) edges[i].dist +=x;
return !ret;
}
}S1;
int main()
{
// freopen("uva11478.in","r",stdin);
// freopen(".out","w",stdout);
while(cin>>n>>m) {
S1.init(n);
For(i,m) {
int a=read()-1,b=read()-1;
S1.addedge(a,b,read());
}
int L = 0 , R = 10001,ans = 0;
if (S1.check(R+1)) {
puts("Infinite");
continue;
} else if (!S1.check(1)) {
puts("No Solution");
continue;
}
while(L<=R) {
int m= (L+R)/2;
if (S1.check(m)) L=m+1,ans=m; else R=m-1;
}
printf("%d\n",ans);
}
return 0;
}