8.20 usaco

summary:14

1.k短路

2.tarjan缩无向图点

3.复习了SA

4.差分约束

5.求第二短路

洛谷3824:dfs优化背包。开始的时候mle了,然后我就把a[i],w[i]去掉。。。。就A了。优化空间。。。 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
} 
const int nmax=10000005;
int sum[nmax],cnt[nmax],ans=0,n,m;
void maxs(int &a,int b){
	if(a<b) a=b;
}
void dfs(int cur,int x,int y){
	if(sum[cur-1]+x<=m) {
		maxs(ans,cnt[cur-1]+y);return ;
	}
	maxs(ans,y);
	dwn(i,cur-1,1){
		if(x+sum[i]-sum[i-1]<=m) dfs(i,x+sum[i]-sum[i-1],y+cnt[i]-cnt[i-1]);
	}
}
int main(){
	m=read(),n=read();int u,v;
	rep(i,1,n) u=read(),v=read(),sum[i]=sum[i-1]+u,cnt[i]=cnt[i-1]+v;
	dfs(n+1,0,0);
	printf("%d
",ans);
	return 0;
}

bzoj1734:裸二分答案。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
} 
const int nmax=1e5+5;
int a[nmax],n,c;
bool check(int x){
	int sum=1,pre=a[1];
	rep(i,2,n) {
		if(a[i]-pre>=x) sum++,pre=a[i];
	}
	return sum>=c;
}
int main(){
	n=read(),c=read();
	rep(i,1,n) a[i]=read();
	sort(a+1,a+n+1);
	int l=0,r=a[n],mid,ans=0;
	while(l<=r){
		mid=(l+r)>>1;
		if(check(mid)) ans=mid,l=mid+1;
		else r=mid-1;
	}
	printf("%d
",ans);
	return 0;
}

bzoj1733:二分答案+最大流就可以了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=205;
const int maxn=160005;
const int inf=0x7f7f7f7f;
struct edge{
	int to,cap,dist,p;edge *next,*rev;
};
edge es[maxn],*pt=es,*head[nmax],*p[nmax],*cur[nmax];
void add(int u,int v,int d){
	pt->to=v;pt->dist=d;pt->cap=pt->p=1;pt->next=head[u];head[u]=pt++;
	pt->to=u;pt->dist=d;pt->cap=pt->p=0;pt->next=head[v];head[v]=pt++;
	head[u]->rev=head[v];head[v]->rev=head[u];
}

int n,m,T,cnt[nmax],h[nmax];
void mins(int &a,int b){
	if(a>b) a=b;
}
int maxflow(){
	clr(cnt,0),cnt[0]=n;clr(h,0);
	int flow=0,a=inf,x=1;edge *e;
	while(h[1]<n){
		for(e=cur[x];e;e=e->next) if(e->cap>0&&h[e->to]==h[x]-1) break;
		if(e){
			mins(a,e->cap),p[e->to]=cur[x]=e;x=e->to;
			if(x==n){
				while(x!=1) p[x]->cap-=a,p[x]->rev->cap+=a,x=p[x]->rev->to;
				flow+=a,a=inf;
			}
		}else{
			if(!--cnt[h[x]]) break;
			h[x]=n;
			for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) h[x]=h[e->to]+1,cur[x]=e;
			cnt[h[x]]++;
			if(x!=1) x=p[x]->rev->to;
		}
	}
	return flow;
}
bool check(int x){
	rep(i,1,n) qwq(i) {
		if(o->dist<=x) o->cap=o->p;
		else o->cap=0;
	}
	return maxflow()>=T;
}
void maxs(int &a,int b){
	if(a<b) a=b;
}
int main(){
	n=read(),m=read(),T=read();int u,v,d,l=0,r=0;
	rep(i,1,m)  u=read(),v=read(),d=read(),add(u,v,d),add(v,u,d),maxs(r,d);
	int ans=0,mid;
	while(l<=r){
		mid=(l+r)>>1;
		if(check(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%d
",ans);
	return 0;
}

bzoj1731:差分约束。s[j]-s[i]<=k/s[j]-s[i]>=k=>s[i]-s[j]<=-k/s[i]-s[i-1]>=0=>s[i-1]-s[i]<=0 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
#define ll long long
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=1005;
const int maxn=30005;
const ll inf=1e15;
struct edge{
	int to,dist;edge *next;
};
edge es[maxn],*pt=es,*head[nmax];
void add(int u,int v,int d){
	pt->to=v;pt->dist=d;pt->next=head[u];head[u]=pt++;
}
queue<int>q;
ll dist[nmax];int cnt[nmax];bool inq[nmax];
bool spfa(int n){
	rep(i,2,n) dist[i]=inf;dist[1]=0;
	clr(inq,0),clr(cnt,0);inq[1]=1,cnt[1]=1;
	q.push(1);
	while(!q.empty()){
		int x=q.front();q.pop();inq[x]=0;
		qwq(x) if(dist[o->to]>dist[x]+o->dist){
			dist[o->to]=dist[x]+o->dist;
			if(!inq[o->to]){
				if(++cnt[o->to]==n) return false;
				q.push(o->to);inq[o->to]=1;
			}
		}
	}
}
int main(){
	int n=read(),ml=read(),md=read(),u,v,d;
	rep(i,1,ml) u=read(),v=read(),d=read(),add(u,v,d);
	rep(i,1,md) u=read(),v=read(),d=read(),add(v,u,-d);
	rep(i,2,n) add(i,i-1,0);
	if(spfa(n)) {
		if(dist[n]==inf) printf("-2
");
		else printf("%lld
",dist[n]);
	}else printf("-1
");
	return 0;
}

bzoj1726:求第二短路。我的写法不知道为什么WA了。。网上的题解也没人和我写的一样。。。

my code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
} 
const int nmax=5005;
const int maxn=2000005;
const int inf=0x7f7f7f7f;
struct edge{
	int to,dist;edge *next;
};
edge es[maxn],*pt=es,*head[nmax];
void add(int u,int v,int d){
	pt->to=v;pt->dist=d;pt->next=head[u];head[u]=pt++;
	pt->to=u;pt->dist=d;pt->next=head[v];head[v]=pt++;
}

struct node{
	int x,dist;
	node(int x,int dist):x(x),dist(dist){};
	node(){};
	bool operator<(const node&rhs)const{
	  return dist>rhs.dist;}
};
priority_queue<node>q;
int da[nmax],db[nmax];
void dijkstra(){
	clr(da,0x7f);clr(db,0x7f);da[1]=0;db[1]=0;q.push(node(1,0));
	int tx,td;
	while(!q.empty()){
		node oo=q.top();q.pop();
		tx=oo.x,td=oo.dist;
		if(td!=da[tx]&&td!=db[tx]) continue;
		qwq(tx) {
			if(da[o->to]>td+o->dist){
				db[o->to]=da[o->to];
				da[o->to]=td+o->dist;
				q.push(node(o->to,da[o->to]));
			}else if(db[o->to]>td+o->dist){
				db[o->to]=td+o->dist;
				q.push(node(o->to,db[o->to]));
			}
		}
	}
}
int main(){
	int n=read(),m=read(),u,v,d;
	rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d);
	dijkstra();
	printf("%d
",db[n]);
	return 0;
}

ac code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
} 
const int nmax=5005;
const int maxn=2000005;
const int inf=0x7f7f7f7f;
struct edge{
	int to,dist;edge *next;
};
edge es[maxn],*pt=es,*head[nmax];
void add(int u,int v,int d){
	pt->to=v;pt->dist=d;pt->next=head[u];head[u]=pt++;
	pt->to=u;pt->dist=d;pt->next=head[v];head[v]=pt++;
}

struct node{
	int x,dist;
	node(int x,int dist):x(x),dist(dist){};
	node(){};
	bool operator<(const node&rhs)const{
	  return dist>rhs.dist;}
};
priority_queue<node>q;
int da[nmax],db[nmax];
void dijkstra(){
	clr(da,0x7f);da[1]=0;q.push(node(1,0));
	int tx,td;
	while(!q.empty()){
		node oo=q.top();q.pop();
		tx=oo.x;td=oo.dist;
		if(da[tx]!=td) continue;
		qwq(tx) if(da[o->to]>td+o->dist){
			da[o->to]=td+o->dist;
			q.push(node(o->to,da[o->to]));
		}
	}
}
void DIJKSTRA(int n){
	clr(db,0x7f);db[n]=0;q.push(node(n,0));
	int tx,td;
	while(!q.empty()){
		node oo=q.top();q.pop();
		tx=oo.x;td=oo.dist;
		if(db[tx]!=td) continue;
		qwq(tx) if(db[o->to]>td+o->dist){
			db[o->to]=td+o->dist;
			q.push(node(o->to,db[o->to]));
		}
	}
}
void mins(int &a,int b){
	if(a>b) a=b;
}
int main(){
	int n=read(),m=read(),u,v,d;
	rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d);
	dijkstra();DIJKSTRA(n);
	int ans=da[n],res=inf,tmp;
	rep(i,1,n) qwq(i){
		tmp=da[i]+db[o->to]+o->dist;
		if(tmp!=ans&&tmp<res) res=tmp;
	}
	rep(i,1,n) qwq(i) mins(res,da[i]+db[i]+o->dist*2);
	printf("%d
",res);
	return 0;
}

bzoj1725:嘛状压dp。。居然忘了mod居然忘了mod居然忘了mod!!!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int mod=100000000;
int sta[10005],a[15],dp[15][10005]; 
int main(){
	int n,m,u,v,d,cnt=0;scanf("%d%d",&n,&m);
	rep(i,0,(1<<m)-1) if(!(i&(i<<1))) sta[++cnt]=i;
	rep(i,1,n) rep(j,1,m){
		scanf("%d",&u);
		a[i]+=(1-u)*(1<<(j-1));
	}
	rep(i,1,cnt) if(!(a[1]&sta[i])) dp[1][i]=1;
	rep(i,2,n) rep(j,1,cnt) if(!(a[i]&sta[j])){
		rep(k,1,cnt) if(!(sta[j]&sta[k])) dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
	}
	int ans=0;
	rep(i,1,cnt) ans=(ans+dp[n][i])%mod;
	printf("%d
",ans);
	return 0;
}

bzoj1718:点双联通分量缩点后叶子节点个数/2就可以了。即是加最少的边让整个图双联通。将tarjan稍微修改一下就可以了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=5005;
const int maxn=20005;
const int inf=0x7f7f7f7f;
struct edge{
	int to,op;edge *next;
};
edge es[maxn],*pt=es,*head[nmax];
void add(int u,int v,int cnt){
	pt->to=v,pt->op=cnt,pt->next=head[u],head[u]=pt++;
	pt->to=u,pt->op=cnt,pt->next=head[v],head[v]=pt++;
}
int pre[nmax],dfs_clock=0,scc_cnt=0,sccno[nmax],in[nmax];bool vis[maxn];
stack<int>s;
void mins(int &a,int b){
	if(a>b) a=b;
}
int dfs(int x){
	int lowu=pre[x]=++dfs_clock;s.push(x);
	qwq(x) {
		if(vis[o->op]) continue;
		if(!pre[o->to]) vis[o->op]=1,mins(lowu,dfs(o->to));
		else if(!sccno[o->to]) mins(lowu,pre[o->to]);
	}
	if(lowu==pre[x]){
		scc_cnt++;int tx;
		while(1){
			tx=s.top();s.pop();
			sccno[tx]=scc_cnt;
			if(x==tx) break;
		}
	}
	return lowu;
}
int main(){
	int n=read(),m=read(),u,v;
	rep(i,1,m) u=read(),v=read(),add(u,v,i);
	dfs(1);
	rep(i,1,n) qwq(i) if(sccno[i]!=sccno[o->to]) in[sccno[o->to]]++;
	int ans=0;
	rep(i,1,scc_cnt) if(in[i]==1) ans++;
	printf("%d
",(ans+1)>>1);
	return 0;
}

bzoj1715:spfa判负圈就可以了,用dfs写会快。挖坑。。。没看清有向边无向边WA了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next) 
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=505;
const int maxn=10005;
const int inf=0x7f7f7f7f;
struct edge{
	int to,dist;edge *next;
};
edge es[maxn],*pt=es,*head[nmax];
void add(int u,int v,int d){
	pt->to=v,pt->dist=d,pt->next=head[u],head[u]=pt++;
}
int dist[nmax],cnt[nmax];bool inq[nmax];
queue<int>q;
bool spfa(int n){
	clr(dist,0x7f);dist[1]=0;
	clr(inq,0);inq[1]=1;
	clr(cnt,0);cnt[1]=1;
	while(!q.empty()) q.pop();q.push(1);
	int tx;
	while(!q.empty()){
		tx=q.front();q.pop();inq[tx]=0;
		qwq(tx) if(dist[o->to]>dist[tx]+o->dist){
			dist[o->to]=dist[tx]+o->dist;
			if(!inq[o->to]) {
				if(++cnt[o->to]==n) return true;
				inq[o->to]=1;q.push(o->to);
			}
		}
	}
	return false;
}
int main(){
	int F=read();
	while(F--){
		clr(head,0);pt=es;
		int n=read(),m=read(),w=read(),u,v,d;
		rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d),add(v,u,d);
		rep(i,1,w) u=read(),v=read(),d=read(),add(u,v,-d);
		if(spfa(n)) printf("YES
");
		else printf("NO
");
	}
	return 0;
}

bzoj1710:区间dp。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=2005;
char s[nmax];
int a[nmax],w[30],dp[nmax][nmax];
int main(){
	int m=read(),n=read();scanf("%s",s+1);
	rep(i,1,n) a[i]=s[i]-'a';
	rep(i,1,m){
		scanf("%s",s);
		w[s[0]-'a']=min(read(),read());
	}
	int k;
	rep(i,1,n-1) {
	  rep(j,1,n-i){
		k=i+j;
		dp[j][k]=min(dp[j][k-1]+w[a[k]],dp[j+1][k]+w[a[j]]);
		if(a[j]==a[k]) dp[j][k]=min(dp[j][k],dp[j+1][k-1]);
	  }
	}
	printf("%d
",dp[1][n]);
	return 0;
}

bzoj1709:暴力枚举

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=105;
int a[nmax][nmax],dp[nmax][nmax];
int xx[9]={0,0,0,1,1,1,-1,-1,-1};
int yy[9]={0,1,-1,1,0,-1,1,0,-1};
int main(){
	int n=read(),K=read(),u,v,tx,ty;
	rep(i,1,K) u=read(),v=read(),a[u][v]++;
	rep(i,1,n) rep(j,1,n) if(a[i][j]){
		rep(k,1,8) rep(t,1,n){
			tx=i+xx[k]*t,ty=j+yy[k]*t;
			if(tx<1||ty<1||tx>n||ty>n) break;
			dp[tx][ty]+=a[i][j];
		}
		dp[i][j]+=a[i][j];
	}
	int ans=0;
	rep(i,1,n) rep(j,1,n) if(dp[i][j]==K) ans++;
	printf("%d
",ans);
	return 0;
}

bzoj1708:。。。背包dp。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define ll long long
ll read(){
	ll x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
ll a[30],dp[10005];
int main(){
	int n=read(),m=read();
	rep(i,1,n) a[i]=read();
	dp[0]=1;
	rep(i,1,n) rep(j,a[i],m) dp[j]+=dp[j-a[i]];
	printf("%lld
",dp[m]);
	return 0;
}

bzoj1707:贪心。将右端点排序后,取适合的最小spf。因为这样子取对后面的影响肯定最小!。有更优但复杂写法挖坑!。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=2505;
struct edge{
	int l,r;
	bool operator<(const edge&rhs)const{
	  return r<rhs.r;}
};
edge es[nmax];
struct node{
	int spf,num;
	bool operator<(const node&rhs)const{
	  return spf<rhs.spf;}
};
node ns[nmax];
int main(){
	int n=read(),m=read();
	rep(i,1,n) es[i].l=read(),es[i].r=read();
	rep(i,1,m) ns[i].spf=read(),ns[i].num=read();
	sort(es+1,es+n+1);sort(ns+1,ns+m+1);
	int ans=0;
	rep(i,1,n){
		rep(j,1,m) {
			if(ns[j].spf>es[i].r) break;
			if(ns[j].spf>=es[i].l&&ns[j].num) {
				ns[j].num--;ans++;break;
			}
		}
	}
	printf("%d
",ans);
	return 0;
}

bzoj1598:A*启发式搜索+最短路求k短路

//#3哇咔咔好开心。。。 
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
#define qaq(x) for(edge *o=h[x];o;o=o->next)
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=1005;
const int maxn=20005;
const int inf=0x7f7f7f7f;
struct edge{
	int to,dist;edge *next;
};
edge es[maxn],*pt=es,*head[nmax],*h[nmax];
void add(int u,int v,int d){
	pt->to=v,pt->dist=d,pt->next=head[u],head[u]=pt++;
	pt->to=u,pt->dist=d,pt->next=h[v],h[v]=pt++;
}
struct node{
	int x,dist;
	node(int x,int dist):x(x),dist(dist){};
	node(){};
	bool operator<(const node&rhs)const{
	  return dist>rhs.dist;}
};
priority_queue<node>q;
int dist[nmax],tm[nmax],ans[105],n,m,K;
void dijkstra(){
	clr(dist,0x7f);dist[1]=0;q.push(node(1,0));
	node oo;int tx,td;
	while(!q.empty()){
		oo=q.top();q.pop();
		tx=oo.x,td=oo.dist;
		if(dist[tx]!=td) continue;
		qaq(tx) if(dist[o->to]>td+o->dist){
			dist[o->to]=td+o->dist;
			q.push(node(o->to,dist[o->to]));
		}
	}
}
void AX(){
	clr(ans,-1);
	if(dist[n]==inf) return ;
	q.push(node(n,dist[n]));node oo;int tx,td,temp;
	while(!q.empty()){
		oo=q.top();q.pop();
		tx=oo.x,td=oo.dist;temp=++tm[tx];
		if(tx==1) {
			ans[temp]=td;
			if(temp==K) break;
		}
		if(temp<=K) qwq(tx) q.push(node(o->to,td-dist[tx]+dist[o->to]+o->dist));
	}
}
int main(){
	n=read(),m=read(),K=read();int u,v,d;
	rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d);
	dijkstra();AX();
	rep(i,1,K) printf("%d
",ans[i]);
	return 0;
}

bzoj1706:离散化+矩阵快速幂 。yyl用map判重而且没用struct写矩阵乘法快了很多。不过关键是map吧。挖坑!我不会用map。。。 而且变量名短+清晰、像这里o.from,o.to,o.dist好丑啊、、、 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int nmax=205;
const int inf=0x3f3f3f3f;
struct edge{
	int from,to,dist;
};
edge es[nmax];
int ns[nmax],cnt=0;
void mins(int &a,int b){
	if(a>b) a=b;
}
struct mtx{
	int a[205][205];
	mtx(){
		clr(a,0x3f);
	}
	mtx operator*(const mtx&o)const{
		mtx tmp;
		rep(i,1,cnt) rep(j,1,cnt) rep(k,1,cnt) mins(tmp.a[i][j],a[i][k]+o.a[k][j]);
		return tmp;
	}
}a,b;
int main(){
	int n=read(),m=read(),s=read(),t=read(),u,v,d;
	rep(i,1,m) {
		edge &o=es[i];o.dist=read(),o.from=read(),o.to=read();
		ns[++cnt]=o.from,ns[++cnt]=o.to;
	}
	sort(ns+1,ns+cnt+1);
	cnt=unique(ns+1,ns+cnt+1)-ns-1;
	
	rep(i,1,m) {
		edge &o=es[i];
		o.from=lower_bound(ns+1,ns+cnt+1,o.from)-ns;
		o.to=lower_bound(ns+1,ns+cnt+1,o.to)-ns;
		b.a[o.from][o.to]=b.a[o.to][o.from]=o.dist;
	}
	
	n--;a=b;
	while(n){
		if(n&1) a=a*b;
		n>>=1;b=b*b;
	}
	s=lower_bound(ns+1,ns+cnt+1,s)-ns;
	t=lower_bound(ns+1,ns+cnt+1,t)-ns;
	printf("%d
",a.a[s][t]);
	return 0;
}
原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5791540.html