1.最短路变形
【题意】给一个图,每条边有个距离和花费,要求创建一个子图,满足0点到其余点的距离总和最小,且边的总花费最小。
【注意】首先,数组要开<<1大;
其次,双关键字的最短路,即最小花费下最短路,要注意优先级就是贪心,可以在优先队列做文章,也可以直接在松弛判断当两条边相同,选择当前花费更加小的代价
#include<cstdio> #include<string> #include<cstdlib> #include<cmath> #include<iostream> #include<cstring> #include<set> #include<queue> #include<algorithm> #include<vector> #include<map> #include<cctype> #include<stack> #include<sstream> #include<list> #include<assert.h> #include<bitset> #include<numeric> #define debug() puts("++++") #define gcd(a,b) __gcd(a,b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a,b,sizeof(a)) #define sz size() #define be begin() #define pu push_up #define pd push_down #define cl clear() #define lowbit(x) -x&x #define all 1,n,1 #define rep(i,x,n) for(int i=(x); i<(n); i++) #define in freopen("in.in","r",stdin) #define out freopen("out.out","w",stdout) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> P; const int INF = 0x3f3f3f3f; const LL LNF = 1e18; const int maxn = 500100; const int maxm = 1e6+10; const double PI = acos(-1.0); const double eps = 1e-8; const int dx[] = {-1,1,0,0,1,1,-1,-1}; const int dy[] = {0,0,1,-1,1,-1,1,-1}; int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}}; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; struct node { int u,v,w,nxt,val; }e[maxn<<2]; int head[maxn]; LL dis[maxn],cost[maxn]; bool vis[maxn]; int n,m,t,tot; void init() { tot=0; ms(head,-1); ms(dis,INF); ms(cost,INF); ms(vis,0); } void add(int u,int v,int w,int val) { e[tot].v=v; e[tot].w=w; e[tot].val=val; e[tot].nxt=head[u]; head[u]=tot++; } void spfa() { queue<int> q; dis[0]=0; vis[0]=1; //cost[0]=0; q.push(0); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i!=-1; i=e[i].nxt) { int v=e[i].v; int w=e[i].w; int val=e[i].val; if( dis[v]>dis[u]+w || ( dis[v]==dis[u]+w && cost[v]>val ) ) { dis[v]=dis[u]+w; cost[v]=val; if(!vis[v]) { vis[v]=1; q.push(v); } } } } } int main() { scanf("%d",&t); while(t--) { init(); scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { int u,v,w,val; scanf("%d%d%d%d",&u,&v,&w,&val); add(u,v,w,val); add(v,u,w,val); } spfa(); LL s1=0,s2=0; for(int i=1;i<n;i++) { s1+=dis[i]; s2+=cost[i]; } printf("%lld %lld ",s1,s2); } } /* 2 4 5 0 3 1 1 0 1 1 1 0 2 10 10 2 1 1 1 2 3 1 2 4 5 0 3 1 1 0 1 1 1 0 2 10 10 2 1 2 1 2 3 1 2 */
2.联通块DFS缩点 + BFS求隐式图最短路
#include <cstdio> #include <algorithm> #include <iostream> #include <string> #include <cstring> #include <vector> #include <stack> #include <queue> #include <cmath> #include <list> #include <deque> #include <map> #include <set> using namespace std; #define ll long long const double PI = acos(-1.0); const int maxn = 101; const int INF = 0x3f3f3f3f; int T,n,m,tot,ans; char mp[maxn][maxn]; int id[maxn][maxn]; int vis[maxn*maxn]; vector<int> edge[maxn*maxn]; int dx[]={0,0,-1,1}; int dy[]={-1,1,0,0}; //http://acm.hnucm.edu.cn/vjudge/contest/view.action?cid=49#problem/F struct node { int x,step; node(int x,int step):x(x),step(step){}; }; void dfs(int x,int y) { char ch=mp[x][y]; for(int i=0;i<4;i++) { int tx=x+dx[i]; int ty=y+dy[i]; if(tx>=0&&tx<n&&ty>=0&&ty<m&&!id[tx][ty]&&mp[tx][ty]==ch) { id[tx][ty]=tot; dfs(tx,ty); } } } void get_edge(int x,int y) { for(int i=0;i<4;i++) { int tx=x+dx[i]; int ty=y+dy[i]; if(tx>=0&&tx<n&&ty>=0&&ty<m&&id[tx][ty]!=id[x][y]) { edge[id[x][y]].push_back(id[tx][ty]); edge[id[tx][ty]].push_back(id[x][y]); } } } int bfs(int st) { int res=-INF; memset(vis,0,sizeof(vis)); queue<node> q; q.push(node(st,0)); vis[st]=1; while(!q.empty()) { node ed=q.front(); q.pop(); res=max(res,ed.step); for(int i=0;i<edge[ed.x].size(); i++) { if(!vis[edge[ed.x][i]]) { vis[edge[ed.x][i]]=1; q.push(node(edge[ed.x][i], ed.step+1)); } } } return res; } int main() { scanf("%d",&T); while(T--) { tot=1; ans=INF; memset(id,0,sizeof(id)); scanf("%d%d",&n,&m); for(int i=0;i<=n*m;i++) { edge[i].clear(); } for(int i=0;i<n;i++) { scanf("%s",mp[i]); } for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(!id[i][j]) { id[i][j]=tot; dfs(i,j); tot++; } } } for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { get_edge(i,j); } } for(int i=1;i<tot;i++) ans=min(ans,bfs(i)); printf("%d ",ans); } }