1. 不可以直接到达的点设为正无穷
2. 自己到自己的距离设为0
3. d [k] [i] [j] 为前k个点中i到j的最短路
降维代码实现
const int N=105;
int d[N][N],n;
void floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}
}
1.将顶点化为两堆,起初第一堆只有起点S一个点
2.每次从第二堆中距离S最近的点取出放入第一堆中,并更新最短路,直到第二堆没有点为止
3.维护出的dis[i]就是S到i点的最小距离了
代码实现
//不去重边版
#include
using namespace std;
const int INF = numeric_limits::max();
struct Edge {
int to;
int weight;
Edge(int t, int w) : to(t), weight(w) {}
};
void dijkstra(int start, int n, vector>& graph, vector& dist, vector& count) {
dist.assign(n, INF);
count.assign(n, 0);
dist[start] = 0;
count[start] = 1;
priority_queue, vector>, greater>> pq;
pq.push(make_pair(0, start));
while (!pq.empty()) {
int u = pq.top().second;
int d = pq.top().first;
pq.pop();
if (d > dist[u]) {
continue;
}
for (int i = 0; i < graph[u].size(); ++i) {
int v = graph[u][i].to;
int w = graph[u][i].weight;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
count[v] = count[u];
pq.push(make_pair(dist[v], v));
} else if (dist[v] == dist[u] + w) {
count[v] += count[u];
}
}
}
}
int main() {
int n, m;
cin >> n >> m;
int start; // 起点
cin >> start;
start--;
vector> graph(n);
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
graph[u - 1].push_back(Edge(v - 1, w));
}
vector dist;
vector count;
dijkstra(start, n, graph, dist, count);
/*for (int i = 0; i < n; ++i) {
cout << "到节点 " << i + 1 << " 的最短距离: ";
if (dist[i] == INF) {
cout << "INF";
} else {
cout << dist[i];
}
cout << ", 最短路数量: " << count[i] << endl;
}*/
for(int i=0;i
应用情境: 在一个正常的图上可以进行k次操作,每次操作只影响目前的状态
1.采用离散化建图
2.有n个点时,1~n表示第一层, (1+i*n)~(n+i*n)表示第i+1层
3.在输入时对每层图间进行连接
代码实现
#include
#define N 10000
#define M 50000
#define K 10
using namespace std;
struct Edge {
int to,ne,w;
} edges[4000000];
int n,m,k,startt,endd;
int h[4000000], idx=0;
int dist[4000000];
bool st[4000000];
void add(int u, int v, int w) {
idx++;
edges[idx].to = v;
edges[idx].ne = h[u];
edges[idx].w = w;
h[u] = idx;
}
void dijkstra() {
priority_queue, vector>, greater > > q;
q.push(make_pair(0,startt));
dist[startt] = 0;
while (!q.empty()) {
int id = q.top().second;
int dis = q.top().first;
q.pop();
if (st[id]) continue;
st[id] = true;
for (int i = h[id]; ~i; i = edges[i].ne) {
int j = edges[i].to;
if (dis + edges[i].w < dist[j]) {
dist[j] = dis + edges[i].w;
q.push(make_pair(dist[j], j));
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
memset(h,-1,sizeof h);
memset(dist,0x3f,sizeof dist);
cin>>n>>m>>k>>startt>>endd;
while(m--){
int a,b,c;
cin>>a>>b>>c;
for(int i=0;i<=k;i++){
add(a+i*n,b+i*n,c);
add(b+i*n,a+i*n,c);
if(i
在一个无向图 G=(V, E)中,独立集是顶点集合 (V) 的一个子集 (S) ,使得 (S) 中任意两个顶点在图中都不相邻,即对于任意的 (u, v in S) ,都不存在边 ((u, v) in E) 。而最大独立集就是所有独立集中包含顶点数量最多的那个独立集。
#include
using namespace std;
const int MAXN = 10005;
vector graph[MAXN];
bool k[MAXN];
int dp[MAXN][2];
void dfs(int u) {
for (int v: graph[u]) {
dfs(v);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
}
int main() {
int n,root;
cin >> n;
for(int i=1;i<=n;i++) cin>>dp[i][1];
for (int i = 1; i > u >> v;
graph[v].push_back(u);
k[u]=true;
}
for(int i=1;i<=n;i++){
if(!k[i]){
root=i;
break;
}
}
dfs(root);
cout << max(dp[root][0], dp[root][1]) << endl;
return 0;
}
在一棵树中,点覆盖是一个顶点集合,使得树中的每一条边都至少有一个端点在这个集合中。最小点覆盖问题就是要找出这样一个点覆盖集合,其包含的顶点数量最少。
dp[u][0]=0,dp[u][1]=1;
dp[u][0]+=dp[v][1];
dp[u][1]+=min(dp[v][0], dp[v][1]);
cout<
对于一个无向图 G=(V, E),其中 V 是顶点集,E 是边集。如果存在一个顶点子集 (D subseteq V),使得对于图中任意一个顶点 (v in V),要么(v in D),要么 v与 D中的某个顶点相邻,那么称 D 是图 G 的一个支配集。
代码实现
#include
using namespace std;
const int MAXN = 20005;
vector graph[MAXN];
bool vis[MAXN],over[MAXN];
int ans;
void dfs(int u,int fa) {
vis[u]=1;
bool f=0;
for (int v: graph[u]){
if(v==fa) continue;
dfs(v,u), f=f||over[v];
}
if(!f&&!over[u]&&!over[fa]) over[fa]=1,ans+=1;
}
int main() {
int n;
cin >> n;
for (int i = 1; i >u>>v;
graph[v].push_back(u);
graph[u].push_back(v);
}
dfs(1,1);
cout<
其中dp[u][i]表示以u为根的子树保留i个树枝时得到的最大苹果数量
3.给的图是无向的
4. Dp外层从大到小遍历(即k~1),内层从小到大
AC代码
#include
using namespace std;
const int maxn= 105;
int k,n,m;
vector graph[maxn],app[maxn];
int dp[maxn][maxn];
void dfs(int u,int fa) {
for (int l=0;l=0;i--){
for(int j=0;j>n>>k;
for (int i = 1; i >u>>v>>w;
graph[v].push_back(u);
app[v].push_back(w);
graph[u].push_back(v);
app[u].push_back(w);
}
dfs(1,0);
cout<
AC代码
#include
#define N 10000
#define M 50000
#define K 10
using namespace std;
struct Edge {
int to,ne,w;
} edges[4000000];
int n,m,k,startt,endd;
int h[4000000], idx=0;
int dist[4000000];
bool st[4000000];
void add(int u, int v, int w) {
idx++;
edges[idx].to = v;
edges[idx].ne = h[u];
edges[idx].w = w;
h[u] = idx;
}
void dijkstra() {
priority_queue, vector>, greater > > q;
q.push(make_pair(0,startt));
dist[startt] = 0;
while (!q.empty()) {
int id = q.top().second;
int dis = q.top().first;
q.pop();
if (st[id]) continue;
st[id] = true;
for (int i = h[id]; ~i; i = edges[i].ne) {
int j = edges[i].to;
if (dis + edges[i].w < dist[j]) {
dist[j] = dis + edges[i].w;
q.push(make_pair(dist[j], j));
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
memset(h,-1,sizeof h);
memset(dist,0x3f,sizeof dist);
cin>>n>>m>>k>>startt>>endd;
while(m--){
int a,b,c;
cin>>a>>b>>c;
for(int i=0;i<=k;i++){
add(a+i*n,b+i*n,c);
add(b+i*n,a+i*n,c);
if(i
dp[u][1] += min(dp[v][0], dp[v][1]);
AC代码
#include
using namespace std;
const int MAXN = 10005;
vector graph[MAXN];
bool k[MAXN];
int dp[MAXN][2];
void dfs(int u) {
for (int v: graph[u]) {
dfs(v);
dp[u][0] += dp[v][1];
dp[u][1] += min(dp[v][0], dp[v][1]);
}
}
int main() {
int n,root;
cin >> n;
for(int i=0;i> u >> m;
for(int j=1;j<=m;j++){
cin>>v;
graph[u].push_back(v);
k[v]=true;
}
}
for(int i=0;i
AC代码
#include
#include
#include
#include
using namespace std;
const int INF = numeric_limits::max();
struct Edge {
int to;
int weight;
Edge(int t, int w) : to(t), weight(w) {}
};
void dijkstra(int start, int n, vector>& graph, vector& dist, vector& count) {
dist.assign(n, INF);
count.assign(n, 0);
dist[start] = 0;
count[start] = 1;
priority_queue, vector>, greater>> pq;
pq.push(make_pair(0, start));
while (!pq.empty()) {
int u = pq.top().second;
int d = pq.top().first;
pq.pop();
if (d > dist[u]) {
continue;
}
for (int i = 0; i < graph[u].size(); ++i) {
int v = graph[u][i].to;
int w = graph[u][i].weight;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
count[v] = count[u];
pq.push(make_pair(dist[v], v));
} else if (dist[v] == dist[u] + w) {
count[v] += count[u];
}
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, m,k;
cin>>k;
for(int l=1;l<=k;l++){
cin >> n >> m;
vector> graph(n);
vector> graph1(n);
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
graph[u - 1].push_back(Edge(v - 1, w));
graph1[v - 1].push_back(Edge(u - 1, w));
}
vector dist;
vector count;
vector dist1;
vector count1;
dijkstra(0, n, graph, dist, count);
dijkstra(0, n, graph1, dist1, count1);
long long ans=0;
for(int i=1;i
AC代码
#include
using namespace std;
const int maxn = 1e6+5;
vector graph[maxn];
int d[maxn],maxx;
void dfs(int u,int fa) {
for (int v: graph[u]) {
if(v==fa) continue;
d[v]=d[u]+1;
if(d[v]>d[maxx]) maxx=v;
dfs(v,u);
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n;
cin>>n;
for (int i=1;i>u>>v;
graph[v].push_back(u);
graph[u].push_back(v);
}
dfs(1,0);
d[maxx]=0,dfs(maxx,0);
cout<
AC代码
#include
using namespace std;
const int N=105;
int d[N][N],n;
void floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
while(n!=0){
for(int i=1;i<=n;i++){
int m,v,w;
cin>>m;
for(int j=1;j<=m;j++){
cin>>v>>w;
d[i][v]=w;
}
}
floyd();
int maxx=1e9,num=0;
for(int i=1;i<=n;i++){
int res=0;
for(int j=1;j<=n;j++){
if(i==j) continue;
res=max(res,d[i][j]);
}
if(maxx>res) maxx=res,num=i;
}
if(maxx==1e9) cout<<"disjoint"<>n;
}
return 0;
}