當時隊友都在做其他的題,我就去看了一下。。。先交幾發最小生成樹wa下,然後就走了
打完比賽dalao們說是斯坦納樹板板。。。行吧(打完比賽太多了,直到現在才有時間,計蒜客也出復現賽了,就去學了一下
先說一下a題題意:先給n個點,點的名字還是英文的,還要記錄一下,然後給出m條邊。之後給出4行,每行兩個點的名字,表示從點a到點b要有連線。如果4個連線有重複的邊,只需算一次。問最後所有對連起來所需要的最短的權值和
然後說一下斯坦納樹吧。。。斯坦納樹主要好像是求解 在圖中選擇幾個點,然後將幾個點連線起來的最短的權值和,最小生成樹是斯坦納樹的特殊情況emmmmmm
斯坦納樹主要是dp+最短路。在求解最短權值和的時候我們先會用
state1和state2是state兩個不同的狀態,state1|state2=state
這樣是第一步的優化
之後我們要用最短路來優化
dp[i][state]=min(dp[k][state]+map[k][i])
第二步優化,首先i k之間要有邊。。。基本和上面差不多
直到斯坦納樹和題意之後就可以套板板了。
但是有乙個問題,就是我們在求解的過程中,會發現用斯坦納樹來求的時候樹的根只有乙個,題目中給的樣例如果用這個方式來求解得出來的是25(這樣是求出一棵樹) 因為題目只需要我們求4對的連線,不需要有多餘的邊。。所以我們還要列舉一下。。。
列舉也不需要所有點列舉,畢竟n<=30,全部列舉超時了,我們只需要列舉給出的8個點。因為是4對,如果我們選了乙個點,那麼相對應的另乙個點我們也要選取(這是必須的),所以列舉最少乙個點,最多4個點(列舉想了好久。。。主要是先選點,然後選狀態)
ac**:
#include #include #include #include #include using namespace std;
typedef long long int ll;
const int maxm=1010;
const int maxn=35;
const ll inf=1e18;
struct node
map[maxm*2];
struct point
n[maxn];
int head[maxm],sum;
int n,m;
ll dp[maxn][maxm],bin[maxn],ans;
int lin[maxn],li;
bool vis[maxn];
mapnum;
queueq;
void addedge(int start,int end,int value)
void init()
bin[0]=1;
for (int i=1;i<=31;i++) bin[i]=bin[i-1]<<1;
init();
for (int i=1;i<=m;i++)
li=0;
for (int i=0;i<4;i++)
for (int k=1;k
}spfa(k);
} ans=inf;cho[0]=-1;
for (int i=1;i<=4;i++)
dfs1(1,i,0);
cout<
return 0;
}
計蒜客 2019 ICPC 南昌邀請賽
目錄 f.sequence 線段樹 單點更新 區間查詢 g.winner 思維 j.prefix 字典樹 k.a good game 樹狀陣列 貪心 題意 定義給定 操作1 格式為0 x y,把ax改為y 操作2 格式為1 x y,求f x,y 分析 不難發現,f l,r 可由以下項異或得到 1 r...
2019ICPC南昌邀請賽A (斯坦納樹)
大致題意 給定n個點,m條邊,給定4對點,要求將這4對點對應聯通,重複用邊只要算一次。思路還是先跑乙個斯坦納樹森林,然後合理狀態有所不同,需要一一對應,也就是對應位置必須同時出現。但是有個坑點,4對點中可能有的點會重複出現,所以對於狀態點用vector存一下相應的圖上點。具體避免方式看 這種模板題,...
2023年南昌ICPC邀請賽網路賽
a 直接跑一下 printf 6 n28 n496 n8128 n33550336 n k 跑一下會出來類似下面的規律 然後四個作為乙個迴圈節,推一下 j 樹剖加主席樹模板 i 單調棧跑一下兩邊最小值的問題,然後st表預處理字首和,接著列舉最小值,找到最遠做貢獻的區間後,分類討論 如果是正數,那就後...